AVR Code Not Working As Expected - Page 1
Forum section: electronics / beginners

author: omiks3
author_rank: Newbie
timestamp: July 11, 2021, 04:33:25 am
content: Hi,I was hoping someone would be able to explain to me what difference these two pieces of code would have on an ATmega328. I’ll start of by explaining the problem I was trying to solve then go into the problem I ran into, and what I did as a workaround using Arduino framework instead of plain AVR C.What I was trying to achieve was to output a 50Hz 9V AC (may not be the right term) voltage using a H bridge to drive an old school doorbell chime. I used a L9110S breakout board that I had laying around paired with an Arduino Nano. This was to be a quick prototype to test if this setup would even work. Because it was such a simple setup, I thought I’d make it a bit harder and write the code in C (shown below). Everything was straight forward and when I checked the output of the 2 pins on the Arduino without the H bridge hooked up, I could see a nice 50Hz alternating signal on the oscilloscope.void setup() {//set pins as outputsDDRD &= (1 << PD2) | (1 << PD3);cli();TCCR1A = 0; // set entire TCCR1A register to 0TCCR1B = 0; // same for TCCR1BTCNT1 = 0; //initialize counter value to 0// set compare match register for 1hz incrementsOCR1A = 157; // = (16*10^6) / (f*1024) - 1 (must be <65536)//f = 50Hz//HAVE TO HALVE OCR1A BECAUSE ONLY SWITCH OUTPUT ONCE PER TICK// turn on CTC modeTCCR1B |= (1 << WGM12);// Set CS10 and CS12 bits for 1024 prescalerTCCR1B |= (1 << CS12) | (1 << CS10);// enable timer compare interruptTIMSK1 |= (1 << OCIE1A);sei(); //allow interrupts//set pins to opposite statesPORTD &= ~(1 << PD2);PORTD |= (1 << PD3);}ISR(TIMER1_COMPA_vect){//toggle pins on and off at 50HzPORTD ^= ((1 << PD2) | (1 << PD3));}void loop() {}When I connected the H bridge it did not switch the output at all. Measuring the pins between the Arduino and H bridge, I found that output pins were only dropping around 280mV instead of 4.8V to ground (shown in first picture). I believe this H bridge has pull ups on the inputs which explains the 280mW drop when the Arduino pin goes “low”. But In this case, I expected “low” to be hard ground.To do a sanity check I wrote the same code in Arduino (shown below) just using delays and everything worked with no hardware change (shown in second picture). So, my question is why there would be a difference in output between these two pieces of code flipping outputs on and off#define DELAY 10void setup() {pinMode(2, OUTPUT);pinMode(3, OUTPUT);}void loop() {digitalWrite(2, HIGH);digitalWrite(3, LOW);delay(DELAY);digitalWrite(3, HIGH);digitalWrite(2, LOW);delay(DELAY);}

author: brucehoult
author_rank: Super Contributor
timestamp: July 11, 2021, 04:58:58 am
content: The first photo seems to be showing 25 Hz, not 50.

author: magic
author_rank: Super Contributor
timestamp: July 11, 2021, 05:21:43 am
content: That's your problem right here:Code:DDRD &= (1 << PD2) | (1 << PD3);It should be|=

author: Nominal Animal
author_rank: Super Contributor
timestamp: July 11, 2021, 05:39:29 am
content: Quote from: omiks3 on July 11, 2021, 04:33:25 amSince DDRD is 0 for inputs and 1 for outputs, you need that to beDDRD |= (1 << PD2) | (1 << PD3);instead.The reason you see a change in the pin states is that the line you used keeps the pins previous states (and sets all other PORTD pins as inputs). PORTD pins all default to inputs, so in practice, that line keeps them as inputs. Then, PORTD bits correspond to the internal pull-ups. So, you weren't actuallydrivingthe outputs, you were just twiddling the internal pull-ups on and off!Also, while it does not matter in practice, better put that DDR inside the interrupts-disabled section (after the cli()), so that interrupts are disabled while changing the pin direction. You see, if the code compiled that into a load-modify-store (instead of sbi/cbi), an interrupt might change the value at perfectly the wrong moment (just after the load). Probably will never happen, but why take any risks, when it's just moving one line of code?

author: omiks3
author_rank: Newbie
timestamp: July 11, 2021, 05:59:06 am
content: Thanks for pointing that out.I've still got a lot to learn when it comes to AVR's

author: omiks3
author_rank: Newbie
timestamp: July 11, 2021, 06:01:12 am
content: @brucehoult I was wondering if someone would pick up on that. It just comes down to me being bad at math thats why I left myself a nice reminder in the comments//HAVE TO HALVE OCR1A BECAUSE ONLY SWITCH OUTPUT ONCE PER TICK