#avr Logs

Aug 17 2020

#avr Calendar

03:34 AM TechChristoph: good morning all
03:48 AM nohit: morning
11:06 AM landau: hello. I have an ATMEGA8535 that uses the ADC converter. I use the ADC ISR to execute some actions such as UART communication. However I found that the ISR is executed only one time at the startup. after that nothing happens, the entire program seems to be stuck...any idea?
11:06 AM landau: thanks
11:07 AM landau: I have the ADCSRA |= (1<<ADSC); that is executed from a timer interrupt routine
11:43 AM landau: hello. I have an ATMEGA8535 that uses the ADC converter. I use the ADC ISR to execute some actions such as UART communication. However I found that the ISR is executed only one time at the startup. after that nothing happens, the entire program seems to be stuck...any idea?thanksI have the ADCSRA |= (1<<ADSC); that is executed from a timer
11:43 AM landau: interrupt routine
11:47 AM cehteh_: landau: first of all better dont do I/O from ISR's
11:47 AM cehteh_: in the ADC interrupt only queue the value to be send
11:47 AM landau: I'm going to share the code
11:48 AM landau: cehteh_ you know some parts already :D
11:48 AM cehteh_: not really, i prolly forgotten :D
11:48 AM landau: ahahah
11:48 AM landau: ok
11:50 AM cehteh_: and then step by step .. set up the adc, toggle a led/pin for debugging w/o sending data
11:50 AM landau: here it is https://pastebin.pl/view/6ad5308b
11:50 AM cehteh_: can you then measure approx half your sampling frequency on the pin
11:51 AM cehteh_: ah now i remmeber
11:52 AM landau: I get a value only after the reset...then everything seems to be stuck
11:53 AM cehteh_: dont do io from interrupts, that might be already the problem
11:53 AM cehteh_: you already do green_led_blink() (how is that defined?)
11:53 AM cehteh_: what happens when you comment the fsbus_send out?
11:54 AM landau: this is defined in another routine
11:54 AM landau: it's a simple led toggle routine with a 1ms delay
11:54 AM cehteh_: how not where :)
11:54 AM landau: extern void green_led_blink(void) { PORTD |= (1 << 7); _delay_ms(1); PORTD &= ~(1 << 7); _delay_ms(1);}
11:55 AM cehteh_: dont use delay ... never ever and esp not in interrupts, no wonder that locks up
11:55 AM landau: ok
11:56 AM cehteh_: your adc interrupt is triggered once per ms right?
11:56 AM landau: I will use TIMER0 to handle the led blink
11:56 AM landau: yes the ADC is triggered by TIMER1
11:56 AM cehteh_: but then you wait there for at least 2 ms? .. that'll never work
11:57 AM landau: I will try to comment the green led part
11:57 AM landau: right now
11:57 AM landau: I will try also the autotrigger mode with TIMER1
11:58 AM landau: I tried with no autotrigger
11:58 AM landau: but does not work
11:58 AM cehteh_: make PIND |= (1 << 7)
11:59 AM cehteh_: that toggles the led in hardware
11:59 AM cehteh_: green_led_blink(void) { PIND |= (1 << 7); }
11:59 AM cehteh_: not more
11:59 AM landau: ok thanks!!
11:59 AM landau: but I need it to blink
12:00 PM cehteh_: comment the fsbus send out as well
12:00 PM cehteh_: forget that for now, just do for debugging
12:00 PM landau: ok but then I have no feedback if it works or not...
12:00 PM cehteh_: make that run
12:00 PM landau: yes
12:00 PM cehteh_: toggling means it blinks
12:01 PM cehteh_: first interrupt turns it on, second of, thrird on ...
12:01 PM landau: ok without the fsbus the code is not stucked anymore
12:01 PM landau: maybe is the fsbus that causes problems...
12:01 PM cehteh_: you can measure half the interupt freq at the led pin
12:01 PM cehteh_: yeha but the les blink was bad as well
12:02 PM landau: yes now the interrupt runs!
12:02 PM cehteh_: ok
12:02 PM landau: so how to deal with fsbus? I need it to send the data...
12:03 PM landau: fsbus sends to the computer through UART
12:03 PM cehteh_: you have some kind of main loop() that spins outside of interrupts, you do i/o from there
12:04 PM landau: yes
12:04 PM cehteh_: i'd prolly use a small queue, in case timing isnt 100% critical and it may becomes congested rarely (like 2-4 elements queue)
12:05 PM cehteh_: 2 elements would be already doubleuffering
12:05 PM cehteh_: doublebuffering, so you may just use that
12:05 PM landau: ok a queue...do you have an example of how to do that?
12:07 PM cehteh_: https://git.pipapo.org/?p=muos;a=blob;f=lib/queue.h;h=486c63125dac1e8cd5d9658339f004f7e0809534;hb=refs/heads/devel
12:07 PM cehteh_: and queue.c
12:07 PM cehteh_: but maybe not exactly how you need it, take it as inspiration and its a bit more than you need
12:08 PM cehteh_: or just start with doublebuffering
12:09 PM landau: O will google it
12:21 PM landau: by doublebuffer you mean the TIMER double buffer?
12:21 PM cehteh_: timer?
12:21 PM cehteh_: no
12:21 PM cehteh_: general doublebuffering
12:21 PM landau: ok
12:21 PM landau: do you have a reference?
12:22 PM cehteh_: https://en.wikipedia.org/wiki/Multiple_buffering
12:22 PM landau: ok
12:23 PM cehteh_: in your case ADC readings only not video frames :D
12:23 PM cehteh_: you have uint16_t adc_data[2];
12:24 PM cehteh_: uhm lets start with a single buffer
12:25 PM cehteh_: uint16_t adc_data; bool adc_ready = false;
12:26 PM cehteh_: in adc_isr() { if(ready) error_omg_shit_broken(); else { adc_data = ADC; }}
12:27 PM landau: ok
12:27 PM cehteh_: in loop() { if (ready) { fsbus_send(adc_data); ready = false;} .....
12:28 PM cehteh_: ready must be volatile
12:29 PM landau: ok let me see..
12:29 PM cehteh_: you understand how this works?
12:29 PM landau: I will copy each line and try to understand it right now..
12:30 PM * cehteh_ just typed that here, i hope thats somewhat correct :D
12:31 PM cehteh_: esp you need some way to handle the error case where your loop() cant digest data fast enough and the isr needs to overwrite or drop it
12:31 PM cehteh_: actually overrwrite is bad, better drop
12:31 PM landau: so the ready flag is into the ADC IRS?
12:32 PM cehteh_: because overwriting has a race condition
12:32 PM cehteh_: nah global
12:32 PM landau: ah ok
12:32 PM cehteh_: adc_data as well
12:32 PM landau: yes they must be global
12:33 PM cehteh_: and the ready flag must be volatile
12:33 PM cehteh_: adc_data as well
12:33 PM landau: what about if I do it in the same .c file?
12:34 PM cehteh_: else the compiler may reoder access
12:34 PM cehteh_: where you put it is completely irrelevant
12:34 PM landau: can I do it in the timer_isr function? I mean this is my main loop
12:34 PM cehteh_: dont do i/o in any isr
12:35 PM landau: I mean in the main loop I only have one function that handle UART incoming RX
12:35 PM cehteh_: you may trigger the adc from your button timer function, that one already runs once per ms
12:35 PM landau: yes this is an idea
12:35 PM landau: using the overflow
12:35 PM cehteh_: yes good then
12:36 PM landau: let me try right now..
12:36 PM cehteh_: is fsbus_send fast? can it never block?
12:36 PM cehteh_: i was under that assumption otherwise its even good to make a copy
12:37 PM landau: it should be fast...
12:37 PM cehteh_: if (ready) { uint16_t adc_data_copy = adc_data; ready = false; fsbus_send(adc_data_copy) ...
12:38 PM cehteh_: this way you need 2 bytes more stack space but fsbus_send can take almost any time it wants
12:40 PM landau: the idea is to get rid of fsbus_snd in the interrupt routine right?
12:40 PM cehteh_: yes
12:40 PM cehteh_: get rid of deadlocks and timing critical things
12:41 PM landau: so far it does not work...
12:41 PM cehteh_: glhf :) make it works step by step
12:41 PM landau: I have this
12:41 PM landau: checkADC(0); if(adc_ready){ fsbus_snd(CID, 0, adc_data, 3); adc_ready=false; }
12:42 PM landau: but it stops when ti reach the if statament
12:42 PM cehteh_: how does the ADC_ISR look?
12:43 PM cehteh_: comment the fsbus_snd out
12:43 PM landau: of course if I get rid of fsbus_snd the program does not work
12:43 PM landau: ISR(ADC_vect){ uint8_t ch; ch=(0x0f & ADMUX); if (ADC<100) { //fsbus_snd(CID, 0b01001000|ch, ADC, 3); //POTS[ch]=ADC; adc_data=ADC; adc_ready = true; }}
12:43 PM landau: here it is the ISR
12:43 PM landau: the ADC<100 is just for debuggin...
12:43 PM cehteh_: see what i saied above: you need to handle the error case (ready is still set)
12:43 PM cehteh_: in the simplest case you drop the new value
12:44 PM cehteh_: if(!adc_ready) { adc_data=ADC; adc_ready = true; }
12:44 PM cehteh_: otherwise you have the race condition writing to adc_data we want to prevent
12:45 PM landau: ok
12:45 PM landau: let me try that!
12:47 PM cehteh_: that wont fix the problem but the race conditon is nasty because you get wrong reads every once a while
12:47 PM landau: ok
12:47 PM landau: yes same as before
12:48 PM landau: now everything inside the ISR is execuded if(!adc_ready)
12:48 PM landau: but I get only one UART send then the program stops working
12:49 PM cehteh_: i dont know the fsbus send thing, a) do you by chance try to send faster than your baudrate would permit? that may lock up
12:50 PM landau: https://pastebin.com/hWzWapKn
12:50 PM cehteh_: b) is fsbus_snd blocking somewhere?
12:50 PM landau: I share the fsbus_snd
12:51 PM cehteh_: nah figure it out by yourself because i want to do my stuff :D
12:51 PM landau: it's simple
12:51 PM landau: https://pastebin.com/aTCy4m5s
12:51 PM landau: ahaha okok
12:51 PM landau: thanks!!
12:51 PM cehteh_: uart_putc(snd_buf[i]);
12:51 PM cehteh_: does that block?
12:51 PM cehteh_: likely
12:51 PM cehteh_: do the adc_data_copy thing from above
12:52 PM cehteh_: and add another led/pin to the board, use that as error indicator
12:53 PM landau: ok
12:53 PM landau: thank you!!
12:53 PM landau: I will try that!
12:53 PM cehteh_: whenever and error happens you set it if(!adc_ready) { adc_data=ADC; adc_ready = true; } else {PORTD |= LED_ERROR}
12:53 PM cehteh_: that at least for debugging
12:53 PM landau: yes
12:54 PM cehteh_: is your project private/gpl? or want to commercialize it?
12:55 PM cehteh_: i could recommend my mµOS since it handles a lot things you need already, but *cough* i didnt need an ADC driver yet haha
12:56 PM cehteh_: anyway i am short afk ... bbl
12:56 PM landau: I do not want to commercialize it
01:28 PM landau: I found that the routine is executed ~7 times before it stops working
01:28 PM landau: very strange
01:35 PM cehteh_: re ...
01:35 PM cehteh_: no expected :D did you do the error led thing?
01:35 PM cehteh_: does that flag?
01:36 PM landau: not yet
01:36 PM cehteh_: btw you could do without the adc_ready interrupt, *if* it is ok that the reads are delayed by one interation/1ms
01:37 PM cehteh_: still add diagnostics, the error led thing, i didnt do the calcs, but i suspect you try to send data faster than your baudrate permits
01:37 PM cehteh_: and that uart_putc() is very likely blocking
01:38 PM landau: usually for keys it works very well
01:38 PM cehteh_: as soon that blocks things go haywire unless you handle that correctly
01:38 PM cehteh_: but you now add a lot more data
01:38 PM landau: I tried with a 1byte variable instead of 2byte because fsbus_snd handles only 8bit
01:39 PM cehteh_: do the calcs!
01:39 PM cehteh_: add the error led, that will at least show you the error
01:39 PM cehteh_: whats the fsbus baudrate?
01:39 PM landau: yes
01:39 PM landau: 19200
01:40 PM cehteh_: ok that is 19200 bits per second ... one serial frame is 10 bits ... so 1920 byte per second
01:40 PM cehteh_: you want to send 3 bytes per ms from ADC right? ... thats 3000 bytes
01:40 PM landau: yes
01:41 PM cehteh_: you see
01:41 PM cehteh_: so you may reduce it to send only every other frame or even less
01:41 PM cehteh_: gives you a chance to rolling average the adc reads for lowpass filtering as well
01:42 PM landau: I need the 8bit resolution
01:42 PM cehteh_: the adc is 10bit
01:42 PM landau: yes but I lower the resolution to 8bit
01:42 PM cehteh_: with rolling average you can even get more bits
01:42 PM cehteh_: and then crop those to 8 bit
01:43 PM cehteh_: either way how fast do you need the data? would be once per 32ms ok?
01:43 PM cehteh_: is that just a potentiometer reading?
01:43 PM landau: yes it's a potentiometer reading
01:44 PM landau: so you suggest to put fsbus_snd into a timer?
01:44 PM cehteh_: i'd go for 16ms then thats not noticeable by a human
01:44 PM cehteh_: no
01:44 PM landau: that fires every 32ms?
01:44 PM cehteh_: no
01:44 PM landau: ok
01:45 PM cehteh_: you still read every 1 ms but doing rolligng average adc_data += ADC - adc-data/16;
01:46 PM cehteh_: and you only fsbus send every 16 iterations/ms or whatever your loop is triggered once per ms or how?
01:46 PM landau: ok so I setup an if
01:46 PM landau: counting
01:46 PM cehteh_: and your loop, by chance is not a timer interript?
01:46 PM landau: this loop is a timer interrupt
01:46 PM landau: that reads the 8x8 matrix
01:47 PM cehteh_: didnt i say: dont do i/o from interrupts?
01:47 PM cehteh_: that counts for all interrupts
01:47 PM landau: yes I know however putting this in the main loop does not work
01:48 PM cehteh_: it will, when done correctly
01:48 PM landau: the RX part does not work anymore
01:48 PM cehteh_: you use the timer to trigger button scanning/reads
01:48 PM landau: yes I know you're right
01:48 PM landau: yes I use the timer for scanning the 8x8 matrix
01:49 PM cehteh_: and you pass the read buttons out of the isr somehow (like the ready flag, but we once talked already abut 'buttons changed') or your queue button events from there, i tihnk you should really use queues
01:49 PM cehteh_: then then mainloop consumes the queue and sends data
01:49 PM cehteh_: that will work with uart_putc blocking or not
01:50 PM landau: yes
01:50 PM cehteh_: the only case when it will not work is when you try to send more data than your baudrate permits :)
01:50 PM landau: ok
01:50 PM cehteh_: so, this should never happen, and if, then you need to handle/flag that somehow
01:51 PM cehteh_: ->error led
01:51 PM landau: ok
01:51 PM cehteh_: then you know that you messed up
01:52 PM cehteh_: btw in muos i have a lot error codes, some (many) can happen asyncronously, there is a bit-array with one bit per possible error and a counter how many errors are flagged
01:52 PM landau: I was looking at this
01:52 PM cehteh_: i set the error led whenever that counter > 0 .... and clear it when it becomes 0
01:53 PM cehteh_: and the code can handle pending errors
01:54 PM cehteh_: for diagnostics/debugging its somewhat helpful to have some tools for diagnostics at hand, actually i even log the sourcfile:linnumber where the last few errors happen in a queue
01:54 PM cehteh_: as you see understanding queues is a important concept :D
01:56 PM landau: you are great!
01:58 PM landau: many thanks
02:03 PM landau: now it works!!!
02:04 PM landau: I setup a counter that sends only every ~16ms! yeahh
02:04 PM landau: many many thanks cehteh_
02:05 PM landau: I still have to better understand what you wrote
02:05 PM landau: but it works!
02:06 PM cehteh_: note that scales the adc res by 16
02:06 PM landau: yes
02:06 PM landau: I'm getting values from 0 to 210 instead of 255
02:06 PM landau: but this is not a big problem
02:07 PM cehteh_: and you need to prime the adc_data once adc_data=adc_read()*16; or something like that in setup
02:08 PM cehteh_: nah i presumed 16bit data dunno what you are doing now, but the raw adc value in 16 bit will be 0..16383
02:08 PM landau: I need to squeeze it to a value from 0 to 255
02:08 PM landau: that's why i prefer 8bit
02:08 PM cehteh_: to get get 8 bit back you need to divide/shift it adc_value>>6
02:09 PM landau: ok
09:42 PM luizhenrique is now known as LHLaurini
11:23 PM day_ is now known as day