Sunday, July 24, 2016

HotKey 3

Building and Programming a prototype


Wiring up the Keypad to the Arduino Leonardo

To wire up the Keypad to the Arduino Leonardo I've soldered some thin copper wire to the connector of the PCB and connected it to an external proto board as you can see in the picture below.


After that was done I wired up a simple adapter board for the Arduino Leonardo.



The schematic for this board is quite simple. It just consists of a 10Pin connector for the keypad, an RGB LED and two connectors for the LC-Diaplay and the Serial debug connection.


Creating the Program / Sketch

After the Keypad was wired up to the Leonardo I had to figure out a way to find get the key presses properly into the Arduino. THANKFULLY there was already a library on the Arduino page which does exactly THAT. I've played around a little bit with it and it seem to work properly.

I've created some test sketches and uploaded them into my GitHub repository.

Now I will need to find a way to replace the original PCB of the Keypad.




Tuesday, March 29, 2016

HotKey 2

The day after the proof of concept

I'm using my Hotkey device now since some days and it is pretty practical for the daily workflow. So I've decided to make a more clean or professional version of the HotKey device.

The surprise


I've ordered one of these external USB number pads for notebooks just to have a look inside if there would be enough space to replace the electronics and maybe reuse the keypad matrix. 



JACKPOT! After I have opened it I figured out that there is plenty of space for my upcoming PCB design and also the Keypad Matrix is not glued to the PCB its connected by a flat flex connector, so that it could be reused completely.

Some reverse engineering 


A closer look to the area above the connector of the keypad shows us that the designer of the PCB was so kind to add some labelled test points for me.



This gave me the ability to quickly figure out which button triggers which row and column.

Ordered by key:
NUMC1 R1
TABC5 R4/C4 R1*C3 R1BCKSPCC4 R2
7C1 R28C2 R29C3 R2"-"C2 R1
4C1 R35C2 R36C3 R3"+"C4 R3
1C1 R42C2 R43C3 R4
Enter
C4 R4
0C1 R500C2 R5.C4 R5


Ordered by column and row:
C1 R1NUMC2 R1-C3 R1*C4 R1/C5 R1
C1 R27C2 R28C3 R29C4 R2BCKSPCC5 R2
C1 R34C2 R35C3 R36C4 R3+C5 R3
C1 R41C2 R42C3 R43C4 R4ENTERC5 R4TAB
C1 R50C2 R500C3 R5C4 R5.C5 R5

Then it was quite easy to also figure out the pin out of the connector:

1234567891011
C1C2C3C4NCR1R2R3R4R5C5

What's Next?

The next step would be to wire up the keypad matrix to the Arduino Leonardo and figure out a proper algorithm to read the key presses from the matrix.

Friday, March 25, 2016

HotKey

The idea and the proof of concept

I use EAGLE, LTspice and a lot of other programs which gain a lot of more power an usability if the commands of the Hotkeys are known. But the main problem is that these program have all different Hotkeys/Commands which will vary from [CTRL]+C over the command "copy" to [F6] for copy something.

Even though I know most of the Hotkeys for each program I have often the problem to mistake them when I quickly switch between the different programs. So I thought about that problem and how I could get rid of it. I saw an Arduino sitting on one of my shelfs collecting some dust and I came to my mind that this litte device can "fake" the behaviour of mouse and keyboard on a computer.

I used this feature of the Leonardo before as it can be seen in one of my previous articles. So I've decided to give it a chance to solve my problem.

The proof of concept

I wired up a "shield" with some buttons for my Arduino Leonardo to test the concept and how I would like it.


I Know it looks ugly but it has worked quite well. Below I prepared the schematic for this shield to get a quick overview over the wiring.



The Shield has nine buttons for the Hotkeys and two to select the current configuration. I also added a RGB LED and a 16x2 LC-Display through the I2C connection to show additional information on the currently active configuration. It also got a connector for the serial output for debugging purposes.

All buttons are biased trough the internal pull up resistors of the MCU so that they switch to ground when they are pushed. This saved me 11 Resistors of wiring effort for the board.

I've added the corresponding Arduino sketch to my github repository. You will need a library for the I2C connection of a LC-Display or just comment the line with the definition of LCD_I2C_ACTIVE out.


#define LCD_I2C_ACTIVE // Uncomment to activate the LCD Output


After some tests...

... I decided that I should follow the idea with a HotKey pad to increase the usability of my favourite programs. So stay tuned for the upcoming articles if you want further information about the HotKey pad.


Friday, August 21, 2015

It's been a while...

...since my last post. And NO I'm not dead!

And there are not really any big news, except that I started to play wit the STM32 ARM Cortex controllers from ST. And yes they are definitely different to 8bit AVR controllers.

Spidermans uncle once said: "With great power comes great responsibility", and that's almost true with these (for me) new controllers. You have to take much more care for the configuration of the I/O, the clocks and the Interrupts.

So my next posts will take a closer look about how to setup the Eclipse IDE under Linux for the ARMs and take a look on the programming of these powerful controllers.

The upcoming posts will be more or less a notebook for me to get these things organized and documented.

TMuel

Thursday, January 9, 2014

FastPins.h or a way to realize really fast IO pin response on the Arduino

During my investigations for the last post I have discovered that there is massive difference in the execution time between the "Arduino way" and the "AVR-GCC way" of setting an output pin.

The result of method 1

  digitalWrite(13,HIGH);
  digitalWrite(13,LOW);

and method 2

  PORTB |= (1<<5);
  PORTB &= ~(1<<5);

is the same, PIN13 with the LED will be switched on and off, except that the first one generates a high pulse of 3.95µs and the second statement gets that handled in just 170ns (0.17µs) on an Arduino with 16MHz. The two pictures below show a comparison of both methods.

Yellow: Original Arduino style
Blue: AVR-GCC style
Zoom of the previous picture

Lets take a look to the pros and cons of both methods

Method 1:

Pro:
  • Super easy just take the original Arduino pin number and set the pin either HIGH or LOW
  • Works on all Arduinos e.g. PIN13 will always be on the same place of the board (UNO, MEGA, Leonardo) 
Con:
  • Slow, it takes 3.95µs to set a pin twice (LOW --> HIGH --> LOW)

Method 2

Pro:
  • Fast, it only takes 0.17µs (32 times faster) to set a pin twice (LOW --> HIGH --> LOW)
  • It could be set more than one pin at a time as long as they are on the same port
Con:
  • Its ugly and cryptic to type
  • The port and the pin number must be known
  • Port and pin number are varying between different boards e.g. PIN13 (LED) is PORTB Pin5 on the UNO, PORTB Pin7 on the MEGA and PORTC Pin7 On the Leonardo
  • Usage makes the Arduino sketch fixed to one board due to different pin assignment
But I still wanted an easy AND fast way to set the output pins. So I figured out that there is something called "preprocessor macros" and to be exact something called "Variadic Macros" which looked like it could be the solution but I didn't understood the documentation until I found this question at stackoverflow.com which brought me on the right way for my solution to make the AVR-GCC code look nice.

Preprocessor macros are text/code snippets which will replace parts of your written program code during the compile cycle of the code, and if possible the calculations are done in the preprocessor during compiling and not at runtime on the Arduino. For example they can be used to make ugly code parts look more readable, and that was exactly that what I wanted.

The Results

I have prepared an include file for the Arduino IDE so that the macros are included into the IDE and I also have written an keywords.txt to highlight the corresponding functions and keywords. It can be downloaded here. Both files must be copied into a sub folder of the Arduino libraries folder.

Due to the disadvantage that the port and the pin number must be known I can highly recommend the homepage of Alberto Piganti to figure out the correct ports and pin numbers. He has prepared a lot of very good pin out diagrams various kinds of Arduinos etc.

Usage of the Library/Include File

The usage is quite easy and more or less self explaining. The first parameter which is given to the function is always the port. If the function only gets two parameters then it sets the complete port to the second value.

  digitalFastWrite(PD,150);

Sets PORTD to 0b10010110

If the function gets three or more parameters then the first parameter is always the port and the last parameter can either be 1 or 0 (HIGH or LOW). This works with up to 8 pins at the same time. All outputs will be set at the same time no matter if only 1 pin is set or if all pins of a port are set.

  digitalFastWrite(PD,0,HIGH);
  digitalFastWrite(PD,0,LOW);

Creates a HIGH LOW pulse on pin 0 of PORTD

  digitalFastWrite(PD,0,1,HIGH);
  digitalFastWrite(PD,0,1,LOW);

Does the same with pin 0&1 of PORTD

Here are some examples to set multiple pins at the same time.

  digitalFastWrite(PD,0,1,2,HIGH);
  digitalFastWrite(PD,0,1,2,LOW);
  digitalFastWrite(PD,0,1,2,3,HIGH);
  digitalFastWrite(PD,0,1,2,3,LOW);
  digitalFastWrite(PD,0,1,2,3,4,5,6,7,HIGH);
  digitalFastWrite(PD,0,1,2,3,4,5,6,7,LOW);

It is also possible to quickly read an digital input. The input and output registers are at different addresses. For this reason use PINx instead of PORTx or Px. If readed from the address of PORTx the status of the internal pullup resistors is read which could be different form the real input state
The following example reads the value of pin 0 from PORTD and copies it into the variable pinState.

  pinState = digitalFastRead(PIND,0);

Until now it is still necessary to use the pinMode() function to set if the pin is an input or an output. But I'm working on it to create something which will be compatible with the above examples so stay tuned.



For further questions just ask it in the comments and I will try to answer them as soon as possible.

Monday, December 23, 2013

3208Clock Part 4: Get started with the HT1632C display driver

There are several ways to get started with the HT1632C display driver. One attempt, and this was also my first step, is to check on Google if someone has already written a driver or a library for the HT1632C. And yes, there are a lot of them.

At first I was playing around with the Arduino library from Adafruit. After some modifications I was able to write something to the display.

A Picture from one my first tests with the Adafruit lib

I also figured out that an update of the complete display (from the frame buffer into the HT1632C display driver) took 8.3ms and was only done with a clock speed of approx 35kHz. Please keep in mind that the ATmega8 of the 3208Clock is running at only 8MHz.

Yellow: Chip Select (CS)
Blue: Clock (WR)

A closer look also showed that the duration of the clock cycles is not equal during the transmission. The frequency of the clock is increasing which means that the time for one period of the clock cycle decreases during the transmission of a 16bit value from 33.6µs to 24.8µs.

Yellow: Chip Select (CS)
Blue: Clock (WR)
Yellow: Chip Select (CS)
Blue: Clock (WR)

At this point I wanted to know 2 things.
  1. Why is the duration of the clock cycles not constant during the transmission?
  2. Why is there only a clock frequency of approx 35 kHz (Datasheet says on page 4 1MHz is ok) which causes a update time for the entire display of 8.3ms?

Investigations and benchmarks

At first I figured out that HT1632::writeScreen() and HT1632::writedata(uint16_t d, uint8_t bits) are the functions of the Adafruit library which take care for the transmission. To have something which makes it easier to investigate I have prepared some small Arduino sketches where I only implemented the corresponding functions.

writedata(uint16_t d, uint8_t bits)

In this function the bit banging except the selection of the chip (CS) is done.

void writedata(uint16_t d, uint8_t bits)
{
  pinMode(_data, OUTPUT);
  for (uint8_t i=bits; i > 0; i--) {
    digitalWrite(_wr, LOW);
    if (d & _BV(i-1)) { digitalWrite(_data, HIGH); }
    else { digitalWrite(_data, LOW); }
    digitalWrite(_wr, HIGH);
  }
  pinMode(_data, INPUT);
}

 Answer for Question No 1

In the line "if (d & _BV(i-1))" happens the magic which causes that the clock cycles are varying during the transmission.

_BV(i-1) is the same like (1<<(i-1)), i is the iterator of the for-loop which is initialized with the number of bits. In the worst case the the iterator i is initialized with 16 which causes that in the check for the if-statement a "left shift operation" is executed 15 times. Because that i gets smaller every bit it has to do less and less shift operations to check the if-statement. And this causes that the clock cycle is not equal over the transmission of multiple bits.

I have fixed the problem with the clock speed by the following code modification:


void writedata(uint16_t d, uint8_t bits)
{
  uint16_t compareBit = 0;
  // 0x8000 -> set MSB
  compareBit = bits == 16 ? 0x8000 : compareBit |= (1<<(bits-1)); 
  
  pinMode(_data, OUTPUT);
  for (uint8_t i=bits; i > 0; i--)
  {
    digitalWrite(_wr, LOW);
    if (d & compareBit) { digitalWrite(_data, HIGH); } // 1
    else { digitalWrite(_data, LOW); } // 0
    compareBit = compareBit >> 1;
    digitalWrite(_wr, HIGH);
  }
  pinMode(_data, INPUT);
}

At the beginning of the function I have made a new variable for the comparison if the DATA pin has to be set. These are some lines more code but in this case the bit shift is only executed once in the for-loop. I also set the compareBit variable in a clever way because the most data packages are 16bit in this case the variable is preset with 0x8000 which is nothing else than setting the MSB true. Otherwise we have a repetitive shift operation for the amount of bits that have to be sent.


After this modification the frequency of the clock has been increased to approx 41.5kHz and the duration for a complete screen refresh is now 6.9ms this is 83% of the time it took before the modification.


Yellow: Chip Select (CS)
Blue: Clock (WR)
 

Yellow: Chip Select (CS)
Blue: Clock (WR)


Answer for Question No 2

After the initial improvement of the clock speed to 41.5kHz it still felt to slow for me. So I have removed all the Arduino specific stuff from the corresponding functions and replaced it by native "avr gcc" code.


void writedata(uint16_t d, uint8_t bits)
{
  uint16_t compareBit = 0;
  // 0x8000 -> set MSB
  compareBit = bits == 16 ? 0x8000 : compareBit |= (1<<(bits-1));
  
  DDRB |= (1<<DATA);
  for (uint8_t i=bits; i > 0; i--)
  {
    PORTB &= ~(1<<WR);
    if (d & compareBit) { PORTB |= (1<<DATA); } // 1
    else { PORTB &= ~(1<<DATA); } // 0
    compareBit = compareBit >> 1;
    PORTB |= (1<<WR);
  }
  DDRB &= ~(1<<DATA);
}


I was not aware that the speed improvement would be factor 10!


Yellow: Chip Select (CS)
Blue: Clock (WR)

Yellow: Chip Select (CS)
Blue: Clock (WR)

All three sketches can be downloaded from my GitHub repository.
Slow is the original code, medium is the code with the bugfix for the varying clock cycle and fast is the code for with all improvements.

Friday, December 20, 2013

The Idea, the Design, the Mistake

I know, it's been a long time since my last post. But I was busy with other stuff and also my laziness (a skill which I have trained close to perfection) has prevent me from doing a new post.

This time I want to write about the good, the bad and the ugly the idea, the design and the mistake.

The Idea

While using an Arduino MEGA 2560 with the Ethernet shield I've discovered that there are still a lot of unused and free pins available.


It covers the pins 14-53 and A8-A15 (A6,A7 are also free but difficult to reach with a additional board).

These pins include:
  • USART 1-3 (14-19)
  • I2C (20,21)
  • PWM (44-46)
  • SPI (50-53)
  • ATmega2560 external memory interface (22-37, 39-41)
  • +5V and GND
This brought me to the idea to make a small prototyping shield for these pins.

The Design

For aesthetic reasons I wanted to make a *duino shaped board so I've downloaded the Arduino Mega 2560 reference design form the Arduino homepage to get the exact measurements for the pins and the board outline. Based on that I was able to create a EAGLE library with some templates (board outlines and connectors) to create own shields for the Arduino Mega.


The Mistake

After a lot of checks of the EAGLE *.brd file and additional checks of each of the Gerber layers I've ordered the the PCB at OSH Park. 24 Days later I've found the boards in a nice purple envelope in my mailbox.

I quickly unpacked the PCBs, fired up my soldering station and searched for some pin headers in my assortment boxes. Just some seconds after I have found the pin headers I have discovered that they do not fit trough the holes of the vias - I experienced a strong feeling of disappointment/frustration :-(

A cigarette later I decided to investigate what went wrong. I have discovered that the drilling of all vias in my design of the board where only 0.8mm and a diameter of at least 1.0mm is necessary to put pin header trough the holes. I've decided to make the holes of the vias for the connectors to the Arduino 1.2mm and the rest of the holes of the prototyping area 1.1mm.
I also have updated all packages in my EAGLE Arduino library

But even if the pin headers do not fit to the board I was able to see that it would fit nicely. So I have ordered the updated revision of the board directly again at OSH Park. In 3-4 weeks I will see the final result.