ESP32 ISR and Optocoupler Double Interrupt (Spurious?)

rsimpsonbusa
Posts: 48
Joined: Tue May 17, 2016 8:12 pm

ESP32 ISR and Optocoupler Double Interrupt (Spurious?)

Postby rsimpsonbusa » Fri Jul 13, 2018 4:38 pm

Hi Everybody.

Does anybody know the reason why a GPIO Input Pin (any, tried a lot 14,21,22,32,35,5,4) has a double interrupt when using a optocoupler (TLP281)?

The setup used is the following:

One ESP32 will manage the Output connection to the opto, basically setting High/Low so that the opto switches the ground signal coming from another ESP32 that has the Interrupt Routine on a pin (14 on the pictures). GROUNDS are NOT tied together. In any case, when grounds are tied, the result is the same.

As you can see in the pictures, the Sender ESP32 sends a single pulse and counts it and the Receiver ESP32 with the interrupt pin receives the Interrupt and sends to a queue with a task that reads the queue and prints (a) the count, (b) the tickcount when the int happened and (c) if the signal was high or low.

The Interrupt pin is set to NEGEDGE, pullup enabled (also tested with an additional 10k pullup).

Code: Select all

void pinTaskIn(void *pArg) { intdef param; param.count=0; param.timer=0; param.lowHigh=0; intdef param1; gpio_config_t io_conf; uint64_t mask=1; io_conf.intr_type = GPIO_INTR_NEGEDGE; io_conf.pin_bit_mask = (mask<<whichPin); io_conf.mode = GPIO_MODE_INPUT; io_conf.pull_down_en =GPIO_PULLDOWN_DISABLE; io_conf.pull_up_en =GPIO_PULLUP_ENABLE; gpio_config(&io_conf); gpio_install_isr_service(0); gpio_set_intr_type(whichPin, GPIO_INTR_NEGEDGE); isrQ = xQueueCreate( 100, sizeof( param ) ); gpio_isr_handler_add((gpio_num_t)whichPin, gpio_isr_handler,(void*)&param); printf("Ready Input\n"); while(1) { if( xQueueReceive( isrQ, &param, portMAX_DELAY )) { printf("Count %d lowHigh %d timer %d\n",param.count,param.lowHigh, param.timer); } vTaskDelay(100/portTICK_PERIOD_MS); } }
As a good measure, doubting the initial NEGEDGE setup was wrong(?), we again set the int type to NEGEDGE.

The result is that for a Single activation of the optocoupler the Interrupt routine has 2 interrupts, one for a Low and another for a High when it is clearly defined only NEGEDGE.

The worst part is that it is not consistent, most of the times it has two interrupts but randomly it has only one (second print screen Count 3).

I have tried Hardware setups like 1.5 K pullup to 300K pullup. No change. A 1uf Cap. Same result.

The sending routine is simple but i attach it so as to have no doubts about the code.

Code: Select all

void pinTaskStep(void *pArg) { mystruct *defs=(mystruct*)pArg; gpio_config_t io_conf; uint64_t mask=1; int sent=0; io_conf.intr_type = GPIO_INTR_DISABLE; io_conf.pin_bit_mask = (mask<<defs->elpin); io_conf.mode = GPIO_MODE_OUTPUT; io_conf.pull_down_en =GPIO_PULLDOWN_DISABLE; io_conf.pull_up_en =GPIO_PULLUP_DISABLE; gpio_config(&io_conf); printf("Ready Output\n"); while(1) { if(sendit) { sent++; printf("Sending[%d] %d\n",defs->elpin,sent); sendit=0; gpio_set_level((gpio_num_t)defs->elpin, 1); vTaskDelay(100/portTICK_PERIOD_MS); gpio_set_level((gpio_num_t)defs->elpin, 0); } vTaskDelay(100/portTICK_PERIOD_MS); } }
Also for good measure a Logic Analyzer was used and it sees only 1 pulse. Please note that the delay is 100ms and the Logic screen has no pulses after 300ms or more.

Also from the interrupt we get that there is Low int and then a High int 100ms after the first. No idea how.

This experiment as done to confirm that a Electric Meter which sends a signal via an optocoupler is not a fault. A Logic Analyzer was used with the meter and had the same results as the experiment with only one pulse registered but 2 ints in the ESP32. I originally thought it was a "noise interference" in the Electric Meter but in our "lab" the result is the same with a simple setup.

Any ideas or suggestions are welcomed.
Attachments
optosetup.jpg
optosetup.jpg (117.25 KiB) Viewed 683 times
Single&3Pulses.jpg
Single&3Pulses.jpg (93.99 KiB) Viewed 683 times
LogicAnalyzer.jpg
LogicAnalyzer.jpg (39.4 KiB) Viewed 683 times

WiFive
Posts: 2052
Joined: Tue Dec 01, 2015 7:35 am

Re: ESP32 ISR and Optocoupler Double Interrupt (Spurious?)

Postby WiFive » Fri Jul 13, 2018 7:42 pm


The result is that for a Single activation of the optocoupler the Interrupt routine has 2 interrupts, one for a Low and another for a High when it is clearly defined only NEGEDGE.
Could it be that due to noise there is a tiny negative edge in the rising signal right at the voltage threshold? Can you use level interrupts instead?

rsimpsonbusa
Posts: 48
Joined: Tue May 17, 2016 8:12 pm

Re: ESP32 ISR and Optocoupler Double Interrupt (Spurious?)

Postby rsimpsonbusa » Fri Jul 13, 2018 10:43 pm

Hi WiFive.

I did use a scope and the signal seemed very normal. It was also stated in https://github.com/espressif/arduino-esp32/issues/1111.

I tried to google level interrupts and did not find anything on the subject. If you can guide me to an example/documentation.

Thanks.

rsimpsonbusa
Posts: 48
Joined: Tue May 17, 2016 8:12 pm

Re: ESP32 ISR and Optocoupler Double Interrupt (Spurious?)

Postby rsimpsonbusa » Fri Jul 13, 2018 10:48 pm


rsimpsonbusa
Posts: 48
Joined: Tue May 17, 2016 8:12 pm

Re: ESP32 ISR and Optocoupler Double Interrupt (Spurious?)

Postby rsimpsonbusa » Tue Jul 17, 2018 5:51 pm

Hi WiFive.

The interrupt routine in the Electric Meter setup had a big error margin, about 10%-12% HIGHER number of interrupts than actual pulses. The routine was modified so as to read the gpio level and only increment counter if signal is low. Still the same error persisted, a little less now than before.

I had to do a Poll Routine instead of an ISR which is like totally against all programming traditional conventions.

Code: Select all

static void pollTask(void * arg) { //will ask state of each meter and see any change from pos to neg while(1) { for (int a=0;a<MAXDEVS;a++){ //MAXDEVS = 3 //A simulated interrupt is a LOW now with a Previous HIGH (state) if(!gpio_get_level((gpio_num_t)who[a].elpin) && who[a].state) { //Change from High to Low // how long ago. Has to be longer the MINBEAT (40ms) if((millis()-who[a].when)>MINBEAT) { who[a].when=millis(); who[a].state=0; currentBeat[who[a].portid]++; beatSave[who[a].portid]++; who[a].fcount++; who[a].beatc++; if((currentBeat[who[a].portid] % GMAXLOSSPER)==0) //GMAXLOSSPER =80 { //every GMAXLOSSPER interval if(beatSave[who[a].portid]>=dia24h[horag]) //dia24h = 800 { who[a].fullkwh=1; beatSave[who[a].portid]=0; who[a].beatc=0; } else who[a].fullkwh=0; xQueueSendFromISR( isrQ, (void*)&who[a],( TickType_t ) 0 ); } } } else //Save the current state of the Pin { who[a].state=gpio_get_level((gpio_num_t)who[a].elpin); who[a].when=millis(); } } delay(40); //as fast as possible and less than or equal MINBEAT } }
There are now 0 errors when using Polling, but if we were to use a battery as power supply it would have been exhausted by now.

Traditional interrupts should work and not resource to really bad coding and programming.

Should this be reported as a Bug or what to do to make this an official bug report.

Robert

WiFive
Posts: 2052
Joined: Tue Dec 01, 2015 7:35 am

Re: ESP32 ISR and Optocoupler Double Interrupt (Spurious?)

Postby WiFive » Tue Jul 17, 2018 7:26 pm

10% error due to noise sounds more like a hardware design issue than a bug. In your photo your test leads are huge antennas. You could try one of the following workarounds
1. Ignore second interrupt within x time since previous interrupt based on known signal parameters
2. Use low level interrupt, switch to high level during low isr, and back to low level during high isr

If you want to use battery you will have to use polling in ulp anyway

rsimpsonbusa
Posts: 48
Joined: Tue May 17, 2016 8:12 pm

Re: ESP32 ISR and Optocoupler Double Interrupt (Spurious?)

Postby rsimpsonbusa » Tue Jul 17, 2018 8:09 pm

Thanks for the prompt answer.

Considering your reply, I have some questions/remarks:

The double int is not on the same edge, that is, first INT gets called with a proper NEGEDGE, which is verified by reading the gpio level, but then the second INT is POSEDGE (isr was setup to be NEGEDGE only) with a confirmed positive level by reading the gpio.

Can it be that the "noise" causes an INT at voltage level so fast that the code reads a positive value some microseconds later? Basically saying that the int flag was raised by ESP32 hw controller but when we read the gpio level (some microseconds in the future) the event has disappeared?

The same leads were used with a direct connection fro ESP-TX to ESP-RX with 0 dups.

Could it be an effect of the optocoupler's actions/internal stuff more than the leads? Like the opto is "bouncing"?

We really need to use optocouplers for many jobs so this is very important.

I'll do some experiments and report back.

Last question, what voltage levels and time is considered an INT? For POSEDGE and NEGEDGE.

Again thanks for the help and guidance.


Robert

rsimpsonbusa
Posts: 48
Joined: Tue May 17, 2016 8:12 pm

Re: ESP32 ISR and Optocoupler Double Interrupt (Spurious?)

Postby rsimpsonbusa » Wed Jul 18, 2018 4:17 pm

Hi WiFive.

After some research I submit the following results as to if there is noise in the environment and if has an effect in the GPIO ISR vs a sw or hw error in the ESP32.

The environment is the same, two ESP32 one that generates a pulse using two alternatives, direct from an GPIO and another via an Optocoupler.

The direct alternative, GPIO to GPIO with shared gnd has NO problem, consistent with the previous experiments.

The second, via Optocoupler, continues to have a double-triple and more int, one for the NEGEDGE and the another unknown, what appears to be positive but not necessarily true.

Additional equipment was used to detect any noise that could cause this so we used (a)Logic Analyzer and (b) Oscilloscope.

Graph 1-4 is the Oscilloscope Capture(upper graph). Appears to be normal, that is 10 pulses(Red is Optos output and Yellow is ESP32 GPIO output).
Graph 2-3 is the Logic Analyzer that also shows (upper graph) 10 pulses but curiously when asked how many falling edges on that sample says 45!!!! Why? How? Sampling rate was at 5msps
So another test but this time in the logic analyzer we set the sampling to 500ksps. That is now Graph 2-3(lower graph) and now we do have 10 pulses and 10 falling edges!!!!!
Graph 1-4(lower graph) is the rising part of the oscilloscope and one can appreciate how slow it is(384us). But relative to what? ESP32 sampling rate I propose which would be great if we knew what it is.

Conclusions.

So, it does not seem to be noise, its rather clean. What appears to be is that the Optocoupler is very slow vs the ESP32 sampling rate, which I have no idea what it is or how and if possible and viable to control it. It takes 384us to get to full Vdd and aprox 200us to get to 1.8Vdd (presuming this is now POSEDGE level) and the ESP32 samples 2-3 times in this interval (still NEGEDGE level), issuing 2 or 3 INTs to the ISR.

BTW the TLP281 Datasheet states the they have a Rise and Fall time of 2-3 us, clearly not the case or something is off (tried with 3 Optos)

So good news, it is the other Hardware not the ESP32. You were right, just not noise.

Regards.

Robert.
Attachments
Graph2-3.jpg
Graph2-3.jpg (154.58 KiB) Viewed 547 times
Graph1-4.jpg
Graph 1 and 4
Graph1-4.jpg (226.65 KiB) Viewed 547 times

WiFive
Posts: 2052
Joined: Tue Dec 01, 2015 7:35 am

Re: ESP32 ISR and Optocoupler Double Interrupt (Spurious?)

Postby WiFive » Wed Jul 18, 2018 7:54 pm

When you have a slow rise time noise is going to be a bigger factor. If you are using an open collector optocoupler and not a logic output optocoupler you need a strong pull-up to have a fast rise time.

Who is online

Users browsing this forum: brp80000, Google [Bot], vonnieda and 13 guests