Friday, 17 July 2015

Nixie Clock with RTC and Bluetooth module



    Although 7 segment LED clocks with radio and alarm circuits are very common in our days and can be found in almost any house, they have some drawbacks like the following:

1. synchronization is done from the 50Hz / 60Hz power line
2. it cannot be used in other grid frequencies that in the one that it was designed
3. they do not have precise backup possibilities
4. they do not have daylight saving
5. you cannot shut down the lights and still have the clock functionality
6. can be powered up just from 230VAC 50Hz/120VAC 60Hz power line

 Because of these drawbacks the designed device presented in this document has the following advantages:
- it uses a RTC circuit that allows the use of a small battery, so the clock will never lose the time, even if it's plugged out(solutions for 4, 5)
- the RTC circuit retains the day, month and year so a daylight saving algorithm can be implemented(solution for 3)
- the RTC circuit has it's own oscillator(solution for 1, 2)
- has a voltage source for all the circuits that can operate either from AC or from DC so it can be powered up with usual DC sources with more than 12V or from a transformer with an output between 12 and 20VAC(solution for 6)

      And above all of mentioned advantages of this design compared to existing 7 segment LED display clocks, the vintage and retro look and feel of Nixie tubes makes from this apparently simple device an one of a kind  special clock.






THE IMPLEMENTATION OF THE CLOCK

NIXIE TUBES BASICS
NIXIE tubes, also known as cold cathode displays or cold cathode tubes are electronics devices used for displaying digits, symbols and alphabetical characters. They are based on the glowing effect of the current passing through a low pressure gas. When a voltage is applied between two metallic terminals, the gas near the terminals is ionized and plasma is generated. The color of the glowing light is dependent of the gas inside the tube.(http://en.wikipedia.org/wiki/Nixie_tube)



NIXIE tubes work with high voltages, of about 140-170V DC and absorb a current of a few milliamp. Most of the Nixie tubes have a common anode, which is the metallic mesh, cylindrically shaped and 10 cathodes, shaped as digits (form 0 to 9) or in some cases other symbols, that are places one in front of another, inside the cylinder. When one wants a cathode to glow, he applies high DC voltage on the anode on the tube, which is in series with a current limiting resistor  and pulls the cathode to the ground (with a driving circuit). There are tubes with two anodes(one responsible for even numbers and one for odd numbers), and cathodes are connected in pairs in parallel (0 with 1, 2 with 3, etc). When one wants to activate one cathode he uses the corresponding anode with the corresponding cathode group. Just the cathode that has the active anode surrounding it will light up.


Nixie tubes have a life or 10-20 000 hours, but it can be extended more than two times by  lowering the anode current and the voltage. There are Nixie tubes , like Philips ZM1000R that have been made with special combination of gases that have a  life of 50 000 or more. Nixie tubes are prone to mechanical failures as cracks of the glass casing, or in cathode poisoning(when some cathodes are not light up as often or at all compared to other cathodes). Cathode poisoning can be avoided if all cathodes are activated(one at a time) periodically, during the operation of the Nixie tube. If one or more cathodes present with poisoning effect, a high current pulse(20mA usually) for short amounts of time are highly likable to “heal” the affected cathode.






DEVICE BLOCK DIAGRAM



1. Power supply schematic

The power supply of the device consists of a full wave rectifier that accepts as input either AC either DC voltage. The output of the rectifier is filtered with an 1000uF capacitor and then fed to two voltage stabilizers: 7805 that generates 5V for the microcontroller, RTC circuit and multiplexers and a 7812 that generates 12V for the alarm, and for the boost power supply for the tubes.





The high voltage for the tube anodes is generated using a boost power supply topology, with a N-MOS transistor as a switching element, and a 1Amp fast rectifier diode as the peak detector. The controller for this power supply is the well known 555 circuit used as an astable multivibrator. The feedback is done by controlling the control voltage inside the circuit using a NPN transistor controlled by a voltage divider that measures the output voltage and feeds current to the base of the NPN transistor.




This schematic is found all over the internet and it is not my intellectual property


2. The microcontroller
The microcontroller is an ATMEL AVR family unit, ATMEGA8535. This microcontroller is pin to pin compatible with ATMEGA16, ATMEGA164, ATMEGA32, ATMEGA324, it has 4 IO ports of 8 bits each that will be used either for inputs, from the buttons, either for output for controlling the tubes, either for communication with the RTC circuit or with the UART.


The microcontroller implements a finite state machine(FSM) and controls the driver of the tubes and reads inputs from the buttons. It continuously reads the RTC circuit and it stores into the RTC circuit the alarm and the hour set by the operatorThe pull-up resistors are not used, the circuit has internal pull down resistors.








3. Driver of the tubes

    The driver is implemented using NPN transistors with a VCEO of more than 80V. The model used is BSX21, models used in old computers that used Nixie tubes as display unit. The transistors have a 5K resistor in series with the base. The 5K resistor is powered by the microcontroller or by the multiplexers and it assures enough current through CE junction, sending the transistor in saturation, thus dissipating the minimum amount of energy.





    If ic is the current through the collector, with a worst case scenario of hfe=20 , output voltage in high state of 3V and a voltage drop between BE junction of 1V, the current in the collector would be about 8mA. But the current through the collector can be maximum the current through the cathode of the tube, the same with the anode that is no more than 2.5mA. Thus, by these approximations we can conclude that the transistor is in saturation. Even if the transistor is not saturated, the power dissipation is still very small, insignificant.

   



    Because of the limitations of the microcontroller, and taken in consideration that maximum one cathode should be lit up at a time, and that not all cathodes are active ( H1 H2 : M1 M2 → H1 : {0 , 1, 2}, H2: {0-9}, M1 : {0-5}, M2: {0-9} ) the microcontroller with control directly some of the transistors and by multiplexers other transistors.





    4. Alarms and configuration buttons

    The device has 5 buttons: Sleep Up Down Set Alarm that have a 100nF capacitor in parallel with them to counteract the effect of bouncing in mechanical buttons. Internal pull-up resistors are used to keep the logic level on the inputs to High when buttons are not pressed.




    The alarm setting has 3 possibilities: a buzzer can act as the alarm, a radio can be powered up through a relay or the alarm can be completely shut off

    5. The PCB
   
The PCB respects basic design rules known by most engineers:
use a ground plane to reduce the noise in the PCB traces. Ground plane should be continuous, with minimum cuts as possible
use decoupling capacitors of 100nF for each integrated circuit on its VCC/ VDD pins
separate digital circuits from analog circuits on the board to reduce interference (capacitive and inductive coupling known as crosstalk)
if ground island plans form try to connect them with thicker traces or with small plans with the biggest ground plan
respect isolation distances for the voltages used on the board

Special conditions have been found and respected for the boost power supply and they will be discussed later in the document.





ALGORITHM OF THE MICROCONTROLLER

The algorithm of the microcontroller is in fact the implementation of a finite state machine.
The algorithm basically performs regularly read function of the RTC circuit. When the SET button is pressed, either minutes or hours flashes.  By pressing the UP / DOWN ,hours, or minutes, depending on which group is in a state of blinking can be changed. To write the new time in the  RTC circuit you press SET for a longer amount of time. To cancel the current operation  the SLEEP button or the ALARM button has to be pressed
When the Alarm button is pressed, either minutes or hours flashes.  By pressing the UP / DOWN ,hours, or minutes, depending on which group is in a state of blinking can be changed. To write the new time in the  RTC circuit you press Alarm for a longer amount of time. To cancel the current operation  the SLEEP button or the Set button has to be pressed
When the alarm is active, it can be silenced by pressing the ALARM OFF. If the operator want to disable it, this can be done by ALM signal switch interrupts.
Also, if the user wants to stop the display, but wants the functionality clock (alarm) to remain active, it may achieve this by operating the ENABLE pin switch that switches the high voltage source that is used to supply tubes onto the  position that is controlled by the microcontroller through EN_HVI signal  the signal  being held at 0V.
For further developments, a jack connector pin to pin compatible with blue-tooth modules was made ​​available. The user can attach a module that is interfaced  by serial connection and he can implement functions to configure the clock from its mobile devices.








DIFFICULTIES ENCOUNTERED AND THE SOLUTION
1. DS1302









Confusion about communication:
    DS1302 uses a Simple 3-Wire Interface for communication. This is not I2C, neither TWI, neither SPI. In the datasheet, the connection between the microcontroller and the DS1302 circuit is done directly
CE has named Reset in previous versions. Its functionality remains the same as in the old circuit and it affects just the communication buffers, and not the RTC functionality.
    It is advised to follow the recommendations in the datasheet and not schematics found on the Internet. The circuit has internal pull down resistors and with pull up resistors you obtain just more current drawn from the PSU, as the pull up resistors form an equivalent resistor with the internal pull down resistors.






2. The boost power supply



Designing PCB for boost power supply has to take in consideration minimizing the hot loops and lowering parasitic inductions.


Also, the design has to be done in such a way to reduce impedances. Vias and ground planes cuts raise impendaces.

http://cds.linear.com/docs/en/application-note/an136f.pdf


3. EMI

    The device is supposed to work wherever it is placed, so it has to be immune to EMI. In the PCB design, AN139 from LT (“ Power Supply Layout and EMI” ) should be taken in consideration.



http://cds.linear.com/docs/en/application-note/an139f.pdf



FUTURE DEVELOPMENT

For future development, the following will be taken in consideration:
developing software for microcontroller so that in can be configured by bluetooth
develop software for Android phone to communicate with the clock for configuration
embed the functionality of the radio onto the board
redesign the device to use less pins of the microcontroller and multiplex in time, the light-up of the digits at the natural frequency of the tubes




Wednesday, 25 March 2015

BikeAngel - it might save you bike, money and time

BikeAngel is an antitheft device aimed to reduce the possibility of a bike being lost and never found again.
 
I am a member of the team developing BikeAngel. My implications are for the development of the device itself (the hardware) and part of the embedded software.

The project can be found here:

https://www.kickstarter.com/projects/bike-angel/bike-angel

It's difference from the rest of the devices that have similar specifications is the fact that it is placed inside the frame of the bicycle and it is not visible and it is very hard to access.




The device consists of a GSM module, a GPS module. The positioning is determined from the GSM cell and the GPS position and the GPS coordinates are transmitted through GSM or GPRS.

Some say that, being inside the bicycle frame means that it is shielded - it's not. Try putting you phone in the microwave oven(with the oven turned off , don't start it...you can even let it unplugged)  and call it(don't turn on the oven).
The phone will ring without a problem.

Put your phone inside a metal case(a STR8 parfume metal casing). It will still work. Shielding depends on materials, thickness, and other stuff, it's not so easy to understand.

And remember, there is an opening on the top.

The device will have an autonomy of 30 days and it will have rechargeable batteries.

I hope I raised your interest for this device. I am opened for suggestions and questions.



Wednesday, 12 June 2013

PWM Configuration for ATMEGA16

     In previous articles we have talked about digital reading, digital writing, now let's learn how to use the timers to generate PWM.
  • What is PWM? For simplicity, let's say it's a square signal with a given frequency and a given duty cycle. For more details refer to this pwm explanation.


  • To generate PWM , we will use the timer
What  is a timer? Well, I'll keep it simple. Let's say that a timer is a unit that counts up or down when a clock edge appears. So if the clock frequency is 10Hz, the counter does something ten times a second.
Atmega16 has three timers called Timer0(8 bit), Timer1(16 bit), Timer2(8 bit).
If a timer is an 8bit timer, it can count up to 2^8-1 = 255. If it is a 16 bit timer, it can count up to 2^16-1 = 65535.

  • For this tutorial we will study Timer0. Timer1 and 2 are configured in the same way. 

Timers have some registers that can be used.
The first one is the Timer/Counter Configuration Register (TCCR0). This register is used to configure the timer, what we want the timer to do, what function to be executed. We said that the timer counts up or down. The number that is increased or decreased will be found in TCNT0 register(8 bit register), so it can be between 0 and 255.
Now, it counts up or down, but the timer can do something like put a pin on "1" or "0" if the timer reaches a limit. This limit is set in the Output Compare Register(OCR0).
TCNT0 is compared with OCR0. On compare match it can generate an interrupt or it can generate a signal to the outside world.

  • Let's have a look in the datasheet at page 83, at Waveform Generation Mode Bit Description Table 38. We can see that for FastPWM we have to set WGM01 and WGM00 to "1".  Now let's have a look at Table 40 Compare Output Mode, Fast PWM Mode and choose from there the third option(non-inverting mode). So, we have to set COM01 to "1". Until now we have configured what function the timer has to execute(non inverting fast PWM). 
  • FastPWM non-inverting works something like this(simple explanation).
TCNT0 is set to 0. You set the duty cycle in OCR Value.
The timer starts counting up, TCNT0 increases. Until TCNT0 doesn't reach the value in OCR0, the output ping OC0 is set to "1". When TCNT0 is greater than OCR0 , OC0 is set to "0".  TCNT0 continues to count up until it reaches the maximum limit of 255, after that it goes back to 0 (cleared) and OC0 is set back to "1".

So that why the frequency between the rising edges of OC0 is (fTimer / 2^8)

Now, we have to set the frequency.

The timer executes when a clock edge appears. The clock is the one that is used for the uC. So , for example is you have a 16MHz clock, this signal will be used as a clock for the timer. However, if you want, you can use this value divided by 8, 64, 256, or 1024 or you can even use an external clock source. The divider is called prescaler.  You can select the clock that is used for the timer by setting CS00 CS01 CS02 bits.

The frequency of your PWM signal will be equal to (CLK freq/(N*256)) where N is the clock divider. 256 is 2^8.

CLKfreq/N is fTimer from the explanation of FastPWM.

  • Having set the mode of operation and the frequency, all that remains is to set the duty cycle. The duty cycle can be set by writing the OCR0 register. The duty cycle will be OCR0value/255. 
  • Also, OC0 is set as OUTPUT, so let us set the correct value in the Data Direction Register .  OC0 is PB3




#include <avr/io.h>
#include <avr/interrupt.h>
#define F_CPU 16000000
#include <util/delay.h>

int main()
{
    TCCR0 |= (1 << WGM00) | (1 << COM01) | (1 << WGM01) | (1 << CS00); /*Configure the timer for FastPWM at frequency of  f =~ 62.5kHz with no prescaling */
    DDRB|=( 1 << PB3 );//set OC0 as output.
    OCR0 = 200;//set the duty cycle(200/255)
   
    while(1); 
    return 0;
}



Usage:

- Modifying the speed of a motor
- Controlling the luminosity of an LED or other element
- Controlling the average voltage
- Controlling servo-motors
-Other things :)

Friday, 15 February 2013

ATMEGA16 Tutorial: Digital Write, Digital Read

Basics for programming an ATMEGA16

1. Digital Write.
When you want to program a uC, you always start from it's datasheet.
http://www.atmel.com/Images/doc2466.pdf

You can see in the datasheet that this uC has 4 8 bit PORTS: PORT A, PORT B, PORT C, PORT D.
Each port can be controlled using 3 registers. PORT, PIN and DDR
You can read in the datasheet at page 51 all the details in the chapter Configuring the Pin.
To summarise:
DDR means Data Direction Register, so using this register we can set if one pin of a port is being used for input or for output.
In the datasheet we can read the following If DDxn is written logic one, Pxn is configured as an output pin. If DDxn is written logic zero, Pxn is configured as an input pin.
Using the PORT register we write to that port, using the PIN register we read from the port.

Case 1:our port is set as output(all 8 pins are output)
            We write to one pin from that port the logic value one
            Result: On that pin we will have aprox 5V.
            We write to one pin from that port the logic value 0
            Result: On that pin we will have aprox 0V
            Everything seems logic....
Case 2:
          our port is set as input
          We write to one pin set as input the  logic value 1
          Result: an internal pull-up resistor is activate.
          We write to one pin set as input the logic value 0
          Result: the internall pull-up resistor is deactivated
What is a pull-up resistor: http://en.wikipedia.org/wiki/Pull-up_resistor
Basically, it is used to pull the pin to VCC when nothing is wired to it. Nothing does not mean 0 logic or 1 logic, so to avoid hazard(noise signal that influences the pin) we pull it to VCC and we know that when nothing is wired, we will have a logic 1.

Now, let's do a digita write on one pin of PORTA for example.

As we can see in the datasheet, PORTA consists of 0 bits (PA7, PA6, ...,PA0).
Let's say we want to write a logic value of 1 to PA6.
PA7, PA5....PA0 will remain unchanged(input or output)
We have to set PA6 as output and write to it.

First, set PA6 as output. We have to make the 7'th bit of DDRA 1, without modifying the rest of the bits.
We know that x | 0 equals x and x | 1 equals 1.
DDRA = DDRA | (1 << PA6 ); 
1 << PA6 means 1 shifted to the felft with PA6 positions. PA6 is defined in a library as 6.
1 << 0 means 00000001
1 << 1 means 00000010
and 1 << PA6 means 01000000 (what we want)
We make a logic or on bits between DDRA and  (1 << PA6). All the bits beside PA6 remain unchanged, and PA6 will become 1 .
Now, we have to write the logic value of 1 to PA6
Using the same technique:

PORTA = PORTA | (1 << PA6);
If we want to write a logic 0 to PORTA and leave the other bits beside PA6 unchanged, we have to use the function & (and)
x & 1 equals x
x & 0 equals 0.  So we have to make a logic and between PORTA and 0 placed at the PA6'th position. Besides that 0, the other bits have to be 1.
1 << PA6  is 01000000
Not changes a logic value:   NOT 1 equals 0
                                          NOT 0 equals 1.
~ is a NOT operator that makes NOT on every bit of the register.
~(1 << PA6) equals 10111111 (exactly what we want)

PORTA = PORTA & (~ (1 << PA6 ));

In C programming language if you have an expression like:

OPERATOR1 = OPERATOR1  operand OPERATOR2
you can write it as:
OPERATOR1 operand = OPERATOR2

For example
a = a + b; <=>  a + = b;
a = a | b <=> a | = b;
a = a & b <=> a & = b;
PORTA = PORTA | (1 << PA6) is the same as PORTA | = (1 << PA6) ;

Another important thing, when using Atmel libraries you have the macro BIT VALUE :
 _BV(PA6) is equal to (1 <<  PA6 ) , so instead of writing the whole (1 <<  PA6 ) you can write  _BV(PA6) and it's the same thing.

PORTA | = (1 << PA6 ); is the same as PORTA | = _BV(PA6);

So, a complete program to write to a pin of a port will be:


#include <avr/io.h>

#define F_CPU 16000000//the cpu is running at 16MHZ)
#include <util/delay.h>

int main() //this is the main function that is being executed when the program starts
 {
while(1)//the program runs continous
  {
    DDRA | = ( 1 << PA6 ); //set PA6 as output
    PORTA | = (1 << PA6); //set PA6 on logic value 1
    _delay_ms(1000);//we wait for 1 second
    PORTA & = ~ (1 << PA6 ); //set PA6 on logic value 0
    _delay_ms(1000);
   }
return 0;
}


This simple program will make PA6 go to 5V, stay 1 second , then go to 0V and stay 1 sec.

2. Digital READ
For digital read we will read pin PD6. If PD6 is HIGH (logical value 1), we will make PA6 go to 5V.
Else, PA6 will be LOW(0V aka logical value 0)
We have to set PD6 to be input, so we have to make the 7'th bit in DDRD 0.

(as we did in the previous case , we will use AND function)

DDRD & = ~ (1 << PD6 ) ; // The PD6th bit will be 0, so it will be an input.
Let's suppose that on PD6 we have connected a button that pul PD6 to GND. We have to activate, for a correct reading of the pin, the internal pull-up resistor.

PORTD | = (1 << PD6 );// we activate the internal pull-up resistor on PD6.

The value of the pin is determined in the following method:
we know that x & 1 equals x, and x & 0 equals 0. We want to tell if PD6 is 1, we don't care about the rest.

PIND & ( 1 << PD6) gives us exactly the value of PD6 - or it's 1("HIGH") , or 0 ( "LOW"). Put this into an if, and voila:




#include <avr/io.h>
#define F_CPU 16000000
#include <util/delay.h>

int main()
{
/* PORT D pins are set as output */
DDRD & = ~ (1 << PD6 ) ; // The PD6th bit will be 0, so it will be an input.
        PORTD | = (1 << PD6 );// we activate the internal pull-up resistor on PD6.
         DDRA | = ( 1 << PA6 ); //set PA6 as output
while(1)
        {
       if((PIND & (1 << PD6))) // if PD6 is "HIGH"
                    {
PORTA |=  ( 1 << PA6 ); // PA6 goes HIGH
    }
else
PORTA & = ~ (1 << PA6 ); //PA6 goes LOW
}

return 0;
}

If you have questions, please comment below

Varying bulb luminosity using ATMEGA16


GENERAL DESCRIPTION

! THE FOLLOWING APPLICATIONS IS DIRECTLY CONNECTED TO 230V POWER LINE. BE CAREFULL. 
! ELECTROCUTION IS POTENTIALY DEADLY.
We know that on the market there are plenty of devices that replace normal wall switches and let you adjust the luminosity of a bulb. But if you want to make an "intelligent" home or a more complicated device to adjust the power of a light bulb what possibilities do you have?

1. If you are using DC , than it's simple: just use a switching element ( a BJT or a MOSFET ). You just apply PWM (Pulse Width Modulation)  and vary the duty cycle from  0% to 99% and you can adjust the luminosity of a lightbulb or LED or you can set the speed of a motor.

2. If  you are using AC .... well you can do the  following:
       2.a. Use a rectifier to obtain DC from AC, filter it and apply what was written at 1.
       2.b.1 Use "something" to turn on and off AC.

If I would use a BJT to implement my application, I would have to consider that in the reverse active region the behavior is different from the forward active region.

Because the application will be used at 50Hz(low frequency) to "drive" a light bulb (small load), and the maximum necessary current that will pass through it will be under 4 - 5 Amps, I have chosen to use a TRIAC. The same application can be easily modified(add some diodes) and can be used to drive high power loads(motors, heating elements, etc) using Thyristors.

In this article, to keep it simple and effective,  I will present how to fire a TRIAC  using an ATMEGA16.


SCHEMATIC

The following schematics will be used:


SCHEMATIC EXPLAINED

We can see that the schematics consists of 6 blocks.
1. Separation block(transformer)
2. Rectifier block
3. Voltage source block
4. 0 crossing detector block
5. Triac block
6. Computational block

1. The galvanic separation is used for safety. The transformer takes the 230V AC from the mains and gives on the output a voltage between 8 to 24V(which is safe tot touch).
This block can be replaced with a group of resistors, capacitors, diodes. IT IS DANGEROUS TO HAVE THE MAINS GO DIRECTLY TO THE MICROCONTROLLER.

2. Use the voltage from the secondary winding of the transformer to power up the uC, and also to detect de 0 crossings of the mains. To power up the uC we need DC, so we take the AC from the transformer and after rectifying(which include a bridge rectifier and a capacitor for filtering) block we obtain DC voltage

3. The uC uses 5V. We take the DC obtained at 2, use it as an input for the 7805 integrated circuit. At the output of the 7805 we will obtain 5V stabilized. We will use this voltage to power up the uC.

4. Zero crossing detector - it's just an opto-coupler. Internally, a diode lights up and turns on or off a photo-transistor which pulls the output to GND. When the transistor is turned off , the output is pulled to VCC by the pull-up resistor.

5. When the output of the uC is HIGH, transistor Q0 is in saturation and the diode inside the opto-triac is lighten and the BT136 TRIAC is fired (it conducts current from A1 to A2).

6. The computational block consists of an ATMEGA16 uC used to run a small program. We use the external interrupt pin INT1 (PD3) and an output(PD7).

CODE


#include <avr/io.h>
#define F_CPU 16000000
#include <util/delay.h>
#include<avr/interrupt.h>



ISR ( INT1_vect )
{
    _delay_ms( 1 );
    TCCR1B |= ( 1 << CS11 );
}

ISR( TIMER1_COMPA_vect )
{
    PORTD |= ( 1 <<  PD7 ) ;
    TCCR1B &= ~ ( 1 << CS11 ) ;
    TCNT1 = 0 ;
    TCCR0 |= ( 1 << CS01 );
}

ISR( TIMER0_COMP_vect )
{
    PORTD &= ~ ( 1 << PD7 ) ;
    TCCR0 &= ~ ( 1 << CS01 ) ;
    TCNT0 = 0 ;
}
int main()
{
    DDRD = ( 1 << 7 ) ;
    PORTD |= ( 1 << PD7 ) | ( 1 << PD3 ) ;
    MCUCR  |= ( 1 << ISC10 ) ;
    GICR |= ( 1 << INT1 ) ;
    TCCR1B = 0x00;
    TCCR1A = 0x00;
    TCCR1B |= ( 1 << WGM12 ) ;
    TIMSK |= ( 1 << OCIE1A ) ;
    OCR1A = 0X09FF;
    TCCR0 = 0x00;
    TCCR0 |= ( 1<<WGM01 ) ;
    TIMSK |= ( 1 << OCIE0 ) ;
    OCR0 = 0XFF;
    sei();
    while(1);
    return 0;
}

CODE EXPLAINED

ISR- means interrupt service request. It is a function that it's called when an interrupt occurs.
TIMER - internal structure of the microcontroller that counts. In our case the timer works in CTC "Clear Timer on Compare" mode. When TCNT(timer register that is incremented with every tick) is equal to OCR an interrupt is generated.

1 << X means 1 shifted to left with X bits
example: 1<<0 means 00000001
and 1<<7 means 10000000

In the main function we make the initialisation for the code to work(initialise the timers, set the interrupts and then wait for something to happen).

When the sinus signal reaches almost 0V, in the detection block a rising or falling edge will be generated. This edge, aplied to PD3(INT1) pin generate an interrupt. When the interrupt appears, the function  ISR ( INT1_vect ) is called. It waits for 1ms(for the voltage to go down to 0 ) and then enables Timer 1 to start counting.the time for the delay until the trigger signal for the opto-triac will be given.
When Timer 1 generates an interrupt(it has finished counting), PD3 pin is set to TRUE(5V) and the trigger signal is sent to the opto-triac which fires the triac that powers on the load (light bulb). Timer 1 is turned off and timer 0 starts counting.
When Timer 0 generates an interrupt(it has finished counting), it means the trigger signal must end , PD3 is set to FALSE(0V) and timer 0 stops counting.

The program will be enhanced in the future to receive the data from USART or ADC and to be set dynamically using an algorithm. Right now, everything is static. This is just a Proof Of Concept.

PCB - it's easy to design, I had no design, just used one board with ATMEGA16 and components soldered in air to it.

Results: 

Trigger signal after 0 crossing with delay:

Trigger signal and signal on the load:


Bulb at low luminosity and signal with trigger for that:




TO BE MENTIONED:
If you want to drive a motor instead of a light bulb, no problem, but you have to use a snubber circuit to protect the TRIAC from damaging because of the inductive load or from auto-triggering.
Also, it's good practice to make the length of the signal until the sinus reaches 0, but it is a little tricky(it is not included in the code). You have to adjust timer 1 for that.
The same stuff can be done with ARDUINO, which uses Atmel microcontrollers and the code can be written in the same stile or using ARDUINO IDE ( I prefer using the presented style, and defenetly not Arduino IDE).

THIS IS MY INTELLECTUAL PROPERTY, if you want to borrow photos or information please ask first.


Article about thyristor: http://en.wikipedia.org/wiki/Thyristor
Article about the TRIAC: http://en.wikipedia.org/wiki/TRIAC
ATMEGA16 Datasheet: http://www.atmel.com/Images/doc2466.pdf 
Hope you like it and it's useful.
If you have something to say (feedback - negative or positive , don't hesitate to post it).

Saturday, 24 November 2012

What things I don't like in Windows - part 1

 This is just a little story about what happened to me today, not a technical debate on Linux vs Windows.

Today I had to run a program that needed to read and load a .bin file from a path. In the configuration file, I have specified a simple path C:\x.bin. I have copied the image at the specified path and tried to run the program. The message was that the file x.bin was not there. I have re-installed the program, restarted my computer and still, I had the same problem.
 
Sick of trying to run this program, I booted up Linux Mint(the OS that I usually use). I was navigating through the files and by mistake I saw that in C: I had a file named x.bin.zip . I rebooted my computer in Windows , unzipped the archive, and tried to run the program that required x.bin . Still, I had an error. Looking up carefully, I saw that x.bin was a folder and inside it was the real x.bin file. When I've tried to copy the file x.bin out of that folder I've got the error that the file that I try to copy had the same name with the folder. I solved that by moving the folder in D: and copy the file back in C:.
 
I don't like that, by default, Windows hides known file extensions. Usually, when I work in Linux and I need to do something, I work in the console. And there, when I try to see the files in a folder, I use the command ls or ls -lh. All the extensions are obvious, and also, I can see if it's a file or a folder.
In conclusion, I prefer using Linux Mint. When I need to run windows programs, I try to run them in Wine or to run them in a Virtual Machine with Windows instead of running Windows OS.