Arduino ADC and auto Triger mode + channel select

Hello!

I have problem with my Arduino mega bord.

I programm my Arduino so that can fast read analog values from analog input pins. Problem acure when i want to read more then one sensor. I need min. 2 analog input for read analog values.

I have:
ADC in auto trigger mode (automatic ADC after one is completed)
Enabled AD interrupt. When AD conversion is over we call interrupt.

In this interrupt i look at ADMUX register and if last 3 bits are all 0 (000) i know its channel 0 to read from. If its (001) i know its channel 1 read from.
But i cant change the channel?
I know its very hard to change channel in auto trigger mode but from datasheet:

If differential channels are used and conversions are started by Auto Triggering, the ADC must
be switched off between conversions. When Auto Triggering is used, the ADC prescaler is reset
before the conversion is started. Since the stage is dependent of a stable ADC clock prior to the
conversion, this conversion will not be valid. By disabling and then re-enabling the ADC between
each conversion (writing ADEN in ADCSRA to “0” then to “1”), only extended conversions are
performed. The result from the extended conversions will be valid. See “Prescaling and Conversion
Timing” on page 278 for timing details.

So what should i do? in ISR disable ADC with ADEN and then change channel, then reenable ADEN?

This is my ISR for ADC

ISR(ADC_vect) {//when new ADC value ready
  cli();
  //rewrite ADMUX register
  //AND it with 0b00000111
  
  //check which channel is in use
  //save value
  //increment mux
  //if chanel 1 is selected (2th. channel - start with 0), reset MUX at channel 0
  
  //save MUX
  tmp = ADMUX;
  tmp1 = ADMUX;
  tmp &= 0x07; //read last 3 bits - 1111000
  
  //uint8_t muxRegisterValue = ADMUX;
  
   
  theLowADC = ADCL; //read ADCL
  theTenBitResults = ADCH <<8 | theLowADC; //read ADCH and save it
   
  //AND it with 0b00000111 # lAST THREE VALUE IN ADMUX register are channel select bits 2^3 = 8 difffrent values CH0 - CH7
  
  if ( tmp == 0)
  {
   theTenBitResultsCH0 = theTenBitResults;
   //ADMUX = ADMUX & 0b11111001;  //Select Channel 1
   ADMUX |= (1 << MUX0);   //Select Channel 1
    delayMicroseconds(125); //w8 betwen channel select?
   //ADCSRA |= 1<<ADSC; //start another convert || we dont need it, we have auto trigger
  }
  else if ( tmp == 1)
  {
    
   theTenBitResultsCH1 = theTenBitResults;
   
   ADMUX &= ~(1 << MUX0);   //Select Channel 0
   delayMicroseconds(125);
   //ADCSRA |= 1<<ADSC; //start another convert || we dont need it, we have auto trigger
   
  }
  else{}
  sei();

P.S. What is best Arduino in free running mode and enable/disable ADC betwen channel select OR in single mode and enable ADC after every conversion and channel select?

It would help if you describe what you are trying to achieve - what are you measuring and how often does it need to be measured?

Are you using the Mega ADC in differential mode?

...R

I measure 2x analog input 4-20mA.

We have stamping tool and with PLC cycle time its to slow for use arhive 1° accurate.

Basicly we have 2 inductive analog sensors which measure high of the tool. We have one inductive proximity sensor which gave us “signal” when to measure height of pressing tool (wheen the press is almost press thogeder).

When we get the signal, we measure high of the tool on PLC. But like i said its to slow for use.
Now we use 200RPM. This is cca. 1mS to get one degree accuracy. Analog-digital covnersion of PLC is very slow. cca 30mS for one reading and cca 60mS for 2 readings. So there is big error.

We try now with AVR. We need to have fast A/D converter with external interrupt for sensor.

IDEA:

  1. Arduino is in auto trigger mode and read analog values all the time. We have 16MHz/64 (prescaler)/13 = cca. 19230Hz. 1/19230 = 0.12mS. So at 200RPM (1mS for one degree) we measure 8x analog value. Thats great.
  2. We call interrupt (external interrupt) when the tool is closed (indicated by external proximity sensor) and in interrupt routine we compare both values to saved ones. If values are greater OR smaler (outside tolarances), we know that there is some stuff in the tool (waste material).

Basically we want speed AND accuracy at the same time (10bit is OK). The programm above is only for ADC interrupt and auto trigger mode. We need conect external proximity switch and program it for external interrupt and values check.

Reply #2 was doing well until it got to the word IDEA.

For the moment please describe the requirement and ignore how it may be implemented in an Arduino.

You say 200RPM and 1ms for 1 degree. By my calculations 200360 is 72000 which is a lot less than 1ms / degree.
Edit to add - silly me I was mixing up minutes and seconds. It would be 200/60
360 =1200, or just less than 1ms per degree
And, in any case, what is rotating at 200 RPM.

You say you have two signals with 4 to 20mA. I presume you are passing the current through a resistor and using the Arduino to measure the voltage across the resistor. What is the range of voltages to be meausured?

You did not answer my question about whether you are using the ADC in differential mode.

Assuming you want to measure two voltages how many samples per second do you need for each of them?
And am I correct to assume you need to interleave the readings?

...R

At 200RPM/60s = 3.3 Hz.... so it make 3 products in 1s

1/3.3s = 0,3030s => for 1 product we need 0.30s (this is time for full circle or one product made)

If we calculate ful circe (360°) => 0.3030/360° = 0,84mS = CCA. 1mS

So at this speed one degree take 0.84mS.

If we take arduino with adc prescaler 64 and adc take 13 cycle we get cca. 19kHz (ADC speed), or ADC is converted every 0.12mS.

So how many reading we get?:
0.84ms/0.12mS = 7 readings

every degree we calulate 7 analog readings. Thats OK.
Lets say that we want in worst case only one reading every degree.

#2 yes. 0-20mA is my output from sensors and i look voltage at resistor (250ohm, at 20mA =5V). Voltage is from 0 - 5V on arduino input.

My problem is not electronics but arduino programming. I want to check one sensor in one cycle and 2th sensor in 2th cycle. We cant measure both sensor at the same time.

I have normal analog input, without differencial mode. Every sensor its on his own channel and i need to check booth if they are inside predefinine values at exactly one point (external interrupt).

Abomination1:
If we take arduino with adc prescaler 64 and adc take 13 cycle we get cca. 19kHz (ADC speed), or ADC is converted every 0.12mS.

So how many reading we get?:
0.84ms/0.12mS = 7 readings

every degree we calulate 7 analog readings. Thats OK.
Lets say that we want in worst case only one reading every degree.

Humble apologies for mixing up minutes and seconds - I have corrected my reply.

However you are still losing me when you venture into Arduino code.

I can't figure if you need (and I mean NEED and not WANT) to take one sample for every degree or if you need to take more samples for every degree - if so what is the minimum number that you need.

I want to check one sensor in one cycle and 2th sensor in 2th cycle

And am I correct to think that you want to read from (say) analog pin A0 for the first degree and from analog pin A1 for the second degree and then back to A0 for the 3rd degree etc.

...R

I want measure at every degree as much reading as its posible. Why?

If want to read as much readings as its posible ofc. with good resoultion. So if i measure 8 readings in one degre and then this readings sum all thogeder and dividet by 8 i get averaging.
Becuz of speed i code it like this : " result >> 3" and save it.

So i want to measure 8 values every degree. So its 16 diffrent values for every degree. This is to much so i accept let say 6 values too and averaging it. The minimum is 1 value every degree, therefore for max value there is no max. value. Max. value depends on arduino speed.

############
max: 8 values every degree
min: 1 value every degree (but there is no averaging)
###############

SO 7 analog readings from one analog input is OK. but I have 2 analog input so i get 3.5 values, so 3 values for AI0 and AI1.

Problem is how to programm to change MUX channel. And how to run ADC? free running or single conversion? What is faster? Dont forget, i need to change analog channel for conersion so: what is faster:

  1. single mode; select channel, run ADC, read ADC, select channel run ADC, OR
  2. free running: select channel, run ADC, read ADC, disable ADC, select channel, enable ADC…

how can i change my programm to auto change channel for every conversion?

You were doing well until you got to "as much as possible". That's not a specification for what the system actually needs. The proper method of design is to work out what you need and then select a microcontroller which can achieve that speed.

I have tried to do the automatic-conversion with interrupts to change the ADC channel and cycle around a set of analog inputs. I got it to work but ultimately it wasn't necessary for my project. The main problem is that you get an interrupt when an analog conversion is complete and you can change the input to be sampled but the next conversion has already started with the previous input. Keeping track of advancing the converter to x+1 while saving the result for x-1 was not easy.

If you have determined that using the default analogRead() isn't fast enough for your purpose then there's two things you can do: first look at changing the DAC clock for faster conversions. You lose some accuracy but you can go a lot faster than the normal Arduino with very little loss. Second, you can pull apart analogRead() and strip out the parts that you don't need.

This second solution is a little more risky from the point of view of future maintainability. Only attempt this if you're close to achieving the required performance. Big speed gains are possible here but the potential costs are huge.

Abomination1:
I want measure at every degree as much reading as its posible. Why?

Let’s try to forget about “as much as possible” for the excellent reasons that @MorganS has put forward.

I still have no clear idea what is the purpose of these analog readings. What are the sensors measuring? Why do you have two sensors? What do you want to do with the data from the sensors?

In other words, please explain what the machine does, how it is controlled and what is the proposed role of the Arduino in that control system.

…R