August 4th, 2009

Matrix keyboard explained

Matrix keyboard setup

In many cases you want to add some input interface to the project, the most simple is to use some push-buttons but what if you need to set some values, some of you might say:  you can do it with up-down, left-right, select button and some clever menu. Yes that’s about right but just imagine the software if you want to set values from 0-9999, or applications like access control, counters.

The most commonly known is the 12 (34) type which has off course 12 buttons noted from 0-9 and *, # for extra features. Well so far there isn’t anything clever about it, 12 buttons which need 12 input pins, wrong it needs just 7, the push buttons are organized in rows and columns, each row shares the same horizontal connection, while each column shares the same vertical connection. For a better understanding look at the schematic:

matrix keyboard schematic

Because of this matrix connection the reading of active button(which is pushed) isn’t so straightforward, each column has to be processed sequentially.

The resistors are external components, there are not included into the keypad but certainly needed, R1-R4 are the pull-up resistor, in the demo application the atmega88’s internal pull-ups are used, R5-R7 are for current limiting.

A few words about the firmware, the keyboard is connected to PORTB, PB0-PB3 are configured as inputs with the internal pull-up active, these will read which row is active, PB4-PB6 are configured as outputs and serve for column selection, their default value is logic ‘1’ the same as the row pins default value. The reading is made sequentially, the first column is selected by setting PB4(COL1) to logic ‘0’ and the pins PB0-PB3 are red, if no key is pressed the pins remain in their default state: logic ‘1’ else their value is logic’0′ we must go trough these steps for each column, once a pressed key is found its space thus value is determined, the function restores the corresponding column select pins default state and exits, this way speeding up the process.

Lets take an example: key 4 is pressed, column 1 is selected by setting PB4 to logic ‘0’, when we read PB0-PB3 PB1 will be logic ‘0’, since we know which column is active (it would be really funny otherwise since we wrote the firmware) the exact location of the pressed key is determined. Now we have 2 coordinates x(0..2),y(0..3)  x=1 is the row, y=0 is the column the most simple way to turn these coordinates into a value is using a 2 dimension look-up table:

const unsigned char KeyMap[3][4] = {{1,4,7,ESC},{2,5,8,0},{3,6,9,ENTER}}; // values ESC and ENTER are defined by macros

By simply addressing the table with the coordinates we have the corresponding value of the pressed key  value = KeyMap[x][y]; the look-up table can also hold any data of choice like ASCII, or can have other type definition as long as its dimension matches the keypads dimension [x][y].

Since the keypad or any other human machine interface tends to be asynchronous, which means that at any moment the firmware should be able to sense and to handle the input, the entire process or in other words the scanning must be executed periodically. This can be done inside some timer interrupt routine or just by adding some delays to the main cycle, if possible avoid using the mains power frequency or any multiple of this for scanning.

Also between the column selection and the effective pin reading some delay must be inserted, this allows time for the electrical state of the wires, traces to stabilize. After one pressed key is sensed the function exits, thus multiple pressed key will not be recorded although the modification needed to the firmware is quite simple, so consider this a challenge.

I attached the entire AVR Studio project, it is written in C, using the winavr package, it will be easy to integrate into any project. In the near future I will explain how to save I/O pins by sharing the row pins with other functions like driving the 7 segment display.

Matrix keyboard explained: [download]

Seven segment display

In this article I intend to explain the functionality and usage of the seven segment display, probably you have seen many projects with these type of displays, however the price drop of LCD’s tend to overtake the market, there are a still few applications for which these devices are more suited. For large numeric displays, like clock’s, railway station displays, low-cost measuring devices or very stressing environments the led based displays are better, and cheaper.  The most simple led display available is the seven segment display, it consists of 7 led stripes arranged forming the number 8, because of its simple construction it is very robust and can function in very low or high temperatures, can withstand vibrations,  mechanical shocks without problems, for what the LCD would fail to work or even get permanently damaged.

single sevene segment

If we look at one digit we can see 10pins each segment and the small dot are LED’s, each of them has one terminal connected to a common pin, from this comes the name common anode or common cathode, and the other terminal is connected to a standalone pin, since the common pin is doubled, we have the 10 pins for each digit.

seven segment config

Lets take as example the common anode type, to light the segments we need to connect the positive supply rail to the common pin, and pull to ground the segments, each segment depending on its size can handle a few miliamps, after all we are talking about LED’s not bulbs. That’s fine if you need just one number to display, but how can these digits be connected to form a multi-digit display? The first approach is to connect each segment to a micro-controller pin, this way for each digit you need 8 pins and isn’t elegant at all.

The other solution is to connect each corresponding segment from the digits to a common bus, and power the digits one at a time, thus multiplexing the data.

seven segment schematic

This multiplexing probably sounds more complicated than it really is, look at the next picture:

illustrated seven segment operation

Since the digits share the same data bus, each digit will have the same number displayed, like the wheel on the picture, to change the number the “data guy” rotates the wheel. So how can we display 1234 you might ask, well wee need another guy, the selector, which will leave only one digit to be seen, all the others are shut off, by synchronizing the “data guy” and the “selector guy ” so they operate at the same time, when the wheel is at the 1111 position, the selector opens the first window, when at 2222 it opens the second and so on. By changing the data and selecting the digits at many times per second the human eye will see a steady image with 1234, the display refresh rate should be above 50 times in 1 second, otherwise the image may flicker.

In the schematic the “selector guy” is implemented by the PNP(BC327) transistors and the “data guy” is the data bus (PORTB0..7). For the practical demonstration I used my own avr development board with ATmega88, four HD1131R type seven segment digits which I rescued from an old TV a few years ago, the connections are made on a prototyping pcb with scrap wires. The data port is PORTB, for selection the PD4..PD7 pins where used.

Like I mentioned earlier we need a periodic data update with digit selection to have a steady image, and since the entire display refresh should be above 50Hz and we have four digits we need to change the digits at frequencies greater than 200Hz. Since the amount of time which one digit is turned on is 1/digit count, as the display has more digits the light intensity gets weaker, in our case the HD1131R has 1.6V voltage drop, by powering from 5V and trough 330Ohm results 10mA trough each segment, but since we have 4 digits the average current received by each segment is 10/4=2.5mA, this will result in a very fade light. For the demo application I used 220Ohm values, with the on board 100Ohm resistors the average current is 2.5mA/segment, although I could have used only the on board resistors, thus having 8.5mA average current, but the peak would be 35mA, and the micro-controller can handle at maximum 25mA/pin, off course the pin won’t get blowed right away from 35-50mA, but you should be careful when designing similar circuits.

That’s enough about the hardware, let’s see the software, for the periodic refresh I used a timer interrupt with 244Hz, resulting in 61Hz refresh rate, in Europe we have 50Hz AC power, so that’s fine, but in the case of 60Hz AC power the refresh rate should be at 70Hz to avoid the stroboscopic effect.

For the display data I used 4 byte buffer from which the interrupt reads and sends to PORTB, the buffer index can be used also for digit selection(see void DisplayData(uint8_t* Display) ).

Because of the seven segment data format by directly writing 5 to PORTB, won’t result in displaying 5, so the numeric data must be converted first, because there isn’t any easy algorithm to mathematically make this conversion, we must use another method, for a one digit display you could make if-else or switch statements, but with 2 digits you already need 100 lines of code, for 3 digits 1000 lines and so on. A very handy solution is a look-up table:

const uint8_t DigitCharTable[] = { DigImage0, DigImage1, DigImage2, DigImage3, DigImage4,\
DigImage5, DigImage6, DigImage7, DigImage8, DigImage9, };

By indexing the table with the numeric value 0-9 we get the needed data format, example PORTB = DigitCharTable[5]; results in displaying 5;

The void NumToDispValue(int16_t Number, uint8_t* DataBuffer) function uses this method to convert 16bit signed value into display compatible string.

After the conversion made, the actual display buffer needs to be updated with the new value, here is a tricky part, by converting 1234 into display compatible data we will have [DigImage1, DigImage2, DigImage3, DigImage4], by having DigImage1 at the first position and my display has  D4,D3,D2,D1 physical configuration the data displayed will look like this: 4321, it gets reversed. This can be overcome by reversing the selection lines PD4..PD7, or by copying the reversed string into the display buffer(see void StrUpdateDisplay(uint8_t* DisplayBuffer, uint8_t* UpdateData, uint8_t InvDir)  ).

After the conversion, the result is a string(not ascii!), so the string manipulation techniques can be easily used, the dot can be added to any digit, simply by setting the 7-th bit in that byte(see macro WITHPOINT(a) in SSDisplay.h ). There is also possible to display a limited amount of characters like E,F,c,C.., (see SSDisplay.h) it won’t be pretty but it’s readable.

Last but not least, since the refresh is done in interrupt, the display buffer update operation should be made atomic, in other words first disable the refresh interrupt, and then update the buffer, otherwise the image will flicker, and don’t forget to re-enable the interrupt after!

If you use only the refresh interrupt, than it’s easier to just disable all interrupts globally, although if you have other interrupt sources too, then disable only the refresh interrupt, this way you won’t hold back the other incoming events.

For data source I used the ADC to measure the potentiometer output, you can also tweak the macro’s used to handle the ADC, the dot in the 2th digit is activated if the ADC value  is above 512.

The demo project was made using avr-gcc and avrstudio, some variable type notations may differ from the ANSI C standard since I use the avr-gcc typedefs, the entire project among with schematics, pdf’s is available for download.

In the next article I will explain the usage of the matrix keyboard.

Seven segment display explained: [download]

January 29th, 2009

Advanced LED display board

Advanced LED display

Like I promised earlier, this is a solution for larger LED displays, with as few as possible pin costs, my solution uses only 7 micro controller pins, and controls 128 LED’s, this can be scaled up to 2048-4096 without problems (check the schematic).


The heart of the schematic is a simple serial to parallel conversion, in other words a shift register (IC1,IC2) this can be connected directly to the SPI of the ATmega88, or to any SPI master. To further optimize the pin count I used a 3 to 8 decoder (IC3), since only one row is powered at any given time there is no use to directly connect the rows to micro controller pins. The schematic contains also the power buffer, which is made with discrete transistors, basically this is also a row to column addressing solution, to prevent the LED’s from flashing when the shift registers are updated the row’s must be disabled for a short time, this can be made with LEN input (IC6 pin6).

Example of a sequence: disable the rows, by pulling LEN to logic 0, update the shit registers via SPI, select the row, enable the row by setting LEN to logic 1. Between the row updates it is usefull to place a delay, makes no sense to have a refresh with a few kHz, this makes the display ligth fade, if the delay is to large the image won’t be steady, you must experiment the optimum refresh rate, my advice is that 50Hz-100Hz of image refresh is enough, this result in 400-800Hz row refresh.

By inserting more shift registers or decoders the resolution of the display can be increased, the only limit is the refresh rate, if you have a large display and you want to make some complicated animation which need a lot of computing and considering also the SPI frequency, the refresh rate could became to slow and the display will flicker.

Advanced LED display board.

AVR ATmega88 development board

We’ve added a new feature to Youritronics, an online shop. We are just starting so for now we only have one item in shop, that is the ATmega88 Development board designed and build by Outsolder Solutions which is a Youritronics partner.

The board features:

  • Board can be powered from AC/DC power, 7.5V-18V/500mA.
  • Firmware can be loaded via preprogrammed bootloader or 6 pin ISP connector.
  • All on board connections made from MCU pins to additional components are made with solder
  • jumpers for easy removal in case of reconfiguration.
  • All MCU pins connected to pin header pins trough 100Ω resistor for short-circuit protection.
  • 5VDC/350mA available on the pin headers, with voltage suppressor protection.
  • Reset circuit and reset button.
  • DB9 connector for serial connection, RS232 to TTL level converter.
  • Potentiometer for ADC input.
  • DC buzzer connected to PWM output.
  • 10 segment led bar controlled by SPI.
  • 2 push buttons for generating external interrupts or general purpose inputs.
  • External crystal oscillator 14,76MHz(not connected, the MCU is set to internal RC 8MHz oscillator).

You can read more about the board at the shop page. (the shop is currently under construction, sorry for any inconvenience.)

July 15th, 2008

Webserver Based On ATMega88

Webserver Based On ATMega88

Before starting this Ethernet project the author did of course some prototyping and then he noticed alreadythat UDP was not a problem with lots of space left on the atmega88. Therefore he was quite confident that TCP + HTTP will work. TCP/IP was invented more than 25 years ago. Todays microcontrollers provide almost the computing power a standard computer had at that time. No java or xml was used at that time. Things were done in smart and efficient ways.

As you can imagine this web-server code is written for a friendly environment. Don’t put it on the open internet. The code uses e.g the incoming packet to build from it the outgoing packet. An attacker who sends a mal formed IP packet might be able to confuse the TCP/IP stack. The code is verified with a lot of different browsers and a number of operating systems. It was tested Linux, BSD Unix, Win 98, Win XP, Mac OS-X with a number of different web browsers. It works very well but it was not tested agains atacks and destroy tests.

Webserver Based On ATMega88: [Link][via]

© 2007-2011 YourITronics | Any logo, trademark and project represented here are property of their respective owners | Wordpress | Privacy Policy    RSS