Hello community!
First of all: thanks a lot for you enourmos efforts of you to help everyone who asks for help. I've spent hours reading through your forum, benefiting of your knowledge.
Nevertheless, this time I was not able to find a solution for my specific problem - even though I thought it should be some kind of standard problem...
First of all, I try to give you all the relevant information needed:
HW: Arduino Due; so far no real sensor in use, only jumper cables for testing purposes of rising and falling edges
My skills: I'm familiar with programming in C, unfortunately not the highest level. Never worked with arduino before my actual project to be honest
My goal: Read (and later on interprete) a manchester protocol. In more detail: The protocol is current modulated with three levels at 7, 14 and 28mA, measured over a 50 Ohm resistor. Thus I have voltage levels at 0.35, 0.7 and 1.4 Volts. The first pulse of the cyclic sent protocol (9 bit long) starts with 28 or 14 mA, after that only data on 7 and 14 mA levels are transmitted.
My problem: As the code is manchester encoded and sent cyclic, I try to catch the beginning and all following edges with an ISR. This ISR should be triggered by a certain voltage (over the lowes level of 0.35V, e.g. 0.5V) and then detect every rising or falling edge. I did a lot of research but my coding experience seems to be too bad to understand everything I can find in regards of the ADC setup. During my research I found that I seem to have two possible ways to solve my problem:
- Use an external comparator which identifies the first rising edge which then sends a digital value to a digital pin to then use an ISR to get the ADC value
OR - Use the ADC configuration to program an comparator within the ADC which then saves the actual value of the ADC within an ISR.
I would love to go with the second solution.
During my research I found a - on the first look - very suitable solution for this:
https://forum.arduino.cc/t/analog-rising-and-falling-edge-detect-and-interrupt-on-arduino-due/640089
Trying to run this code on my Due after the mentioned modifications (placing the "ADC->ADC_ISR;" at the end and switching thresholds to "if (!Look_for_Rising){ADC->ADC_CWR = ADC_CWR_LOWTHRES(2048) | ADC_CWR_HIGHTHRES(4095);} // looking for falling"), I got some ghost edges detected from time to time. Also during startup I already get some rising edges detected.
Most confusing for me so far: the serial monitor detects edged independent of which analog pin I use. I tried DAC1, DAC2, A0, A1 and for all of them some edged are detected. Also I always get the pair of rising and falling edge right after each other - the Pin is still "connected" to the 3.3V board supply pin so no falling edge should be detected?!
What did I mess up here?
One addition which might cause some problems later on: I just need an ADC resolution of 8 Bit. As I understand, this could be easily done with modifying
"ADC_MR_LOWRES_BITS_12
" to "ADC_MR_LOWRES_BITS_8
"?
I hope some of you have an idea how to solve my problem
Here is my complete code so far:
volatile boolean Look_for_Rising=true; // true is looking for rising/false is looking for falling
void setup() {
Serial.begin(115200);
adc_setup();
}
void loop() {
}
void adc_setup ()
{
PMC->PMC_PCER1 |= PMC_PCER1_PID37; // ADC power ON
ADC->ADC_WPMR = 0x41444300; // Disable write protect
ADC->ADC_CR = ADC_CR_SWRST; // Reset ADC
ADC->ADC_MR |= ADC_MR_FREERUN_ON // ADC in free running mode
| ADC_MR_LOWRES_BITS_12 // 12 bits resolution
| ADC_MR_PRESCAL(1)
| ADC_MR_SETTLING_AST3
| ADC_MR_TRACKTIM(10)
| ADC_MR_TRANSFER(2);
ADC->ADC_EMR = ADC_EMR_CMPMODE_OUT // Generates an event when the converted data is out of the comparison window.
| ADC_EMR_CMPSEL(0) // Compare channel 0 = A7
| ADC_EMR_CMPFILTER(0); // Number of consecutive compare events necessary
// to raise the flag = CMPFILTER+1
ADC->ADC_CWR = ADC_CWR_LOWTHRES(0) | ADC_CWR_HIGHTHRES(2047); // at beginning, looking for rising edge
ADC->ADC_CHER = ADC_CHER_CH0; // Enable Channel 0 = A7
ADC->ADC_IER = ADC_IER_COMPE; // Interrupt on Compare match enable
NVIC_EnableIRQ(ADC_IRQn); // Enable ADC interrupt
}
void ADC_Handler() {
// print what kind of interrupt is this
// 1=found Rising edge; 0=found Falling edge
//Serial.print("Looking for rising (1) or falling(0): ");
if (Look_for_Rising == false){
Serial.print("now looking for falling (0)! ");
}
if (Look_for_Rising == true){
Serial.print("now looking for rising (1)! ");
}
Serial.println(Look_for_Rising);
Look_for_Rising=!Look_for_Rising; // invert what to looking for
if (!Look_for_Rising){ADC->ADC_CWR = ADC_CWR_LOWTHRES(2048) | ADC_CWR_HIGHTHRES(4095);} // looking for falling
if (Look_for_Rising) {ADC->ADC_CWR = ADC_CWR_LOWTHRES(0) | ADC_CWR_HIGHTHRES(2047);} // looking for raising
ADC->ADC_ISR; // Read and clear status register
}
Edit: So far I did not modify the thresholds in such a way to identify the three different levels - this needs to be done after I got a working code for only a digital rising/falling edge.