Pages: [1]   Go Down
Author Topic: How to apply ADMUX fuction to a multi analog inputs system  (Read 846 times)
0 Members and 1 Guest are viewing this topic.
Offline Offline
Newbie
*
Karma: 0
Posts: 3
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Greeting all, (and sorry about my poor English)

I was doing my project until got stuck by ADC. I'm new to Arduino so some of my questions may look quite silly to you guys, but please help.

The purpose of this un-finished code is to firstly handle the analog input from pin A0, A2 and A1 as an interrupt, then convert both of them into digital signals by using ADMUX, and then pass them to FFT execute module.

Question 1: Do I need to import the AVR library if I'm going to use some AVR variables and methods? How about stdint library?
             2: How do I make the ADMUX handle two or more analog inputs? I have looked up thishttp://openenergymonitor.blogspot.com.au/2012/08/low-level-adc-control-admux.html, but still don't know how to implement ADMUX such that it can "catch" two or more analog inputs simultaneously (doable?).

Here is the relative code: 
Code:
// free running ADC mode, f = ( 16MHz / prescaler 64 ) / 13 cycles per conversion = 19`231 Hz
  ADMUX = _BV(REFS0) | eva_OUTA; //| eva_OUTB; how to make it take other input?
  ADCSRA = _BV(ADSC) | _BV(ADEN) | _BV(ADATE) | _BV(ADIE) | _BV(ADPS2) | _BV(ADPS1); // | _BV(ADPS0);


And if it helps, here is the full un-finished code.
Code:
#include <LiquidCrystal.h>
#include <ffft.h>
#include <stdint.h>      //Necessary?
#include <avr/interrupt.h>


//LCD pin connection:
#define LCD_D4 5
#define LCD_D5 4
#define LCD_D6 1
#define LCD_D7 0
#define LCD_RS 12
#define LCD_En 11

//Evaluation board pin connection:
#define eva_OUTA A0
#define eva_OUTB A2
#define eva_OUTN A1
#define eva_TEMP A5

//Interrupt buttons connection with condition:
#define flip_page_button 0
#define reset_button 1
volatile int FP = HIGH; // active low
volatile int Reset = HIGH;

//Battery condition monitor connection:
#define bat A4
float Temp;


//initialize the lcd lib and interface pins:
LiquidCrystal lcd(LCD_RS, LCD_En, LCD_D4, LCD_D5, LCD_D6, LCD_D7);

/////////////////////////////////Signal capture using interrupt
volatile  byte  position = 0;
volatile  long  zero = 0;
int16_t capture[FFT_N];                //Pre-locate wave aptureing buffer
complex_t bfly_buff[FFT_N];            // FFT buffer
uint16_t spektrum[FFT_N/2];            // Spectrum output buffer


// free running ADC fills capture buffer
ISR(ADC_vect)
{
  if (position >= FFT_N)
    return;

  capture[position] = ADC + zero;
  if (capture[position] == -1 || capture[position] == 1)
    capture[position] = 0;

  position++;
}

///////////////////////////////////////////setup program:
void setup() {
  /* Make sure all pins are put in high impedence state and
   that their registers are set as low before doing anything.
   This puts the board in a known (and harmless) state */
  for (int i=0;i<20;i++) {
    pinMode(i,INPUT);
    digitalWrite(i,0);
  }
  /* initialize serial */
  //pinMode(4, OUTPUT);
  //Serial.begin(115200);

  Temp=0.0; //initiate teamperature value

  ////////////////////////////Welcome LCD ///////////////////////////////
  //set up LCD's number of columns and rows:
  lcd.begin(16,2);
  //print welcome line
  lcd.setCursor(0,0); //write in the first line
  lcd.autoscroll();
  lcd.print("***** System");
  lcd.noAutoscroll();
  lcd.setCursor(0,1); //write in the second line
  lcd.autoscroll();
  lcd.print("*******");
  lcd.noAutoscroll();
  ///////////////////////////////////End welcome LCD //////////////////////
  sei(); //enable global interrupts for ADC and Pushbuttons
  ///////Button Interrupt////////////////////
  attachInterrupt(flip_page_button, FLIPPAGE, CHANGE);
  attachInterrupt(reset_button, RESET, CHANGE);

  ////////////////////////Signal input handling/////////////////////////
  // ADC channel to capture
  //ADC channel: OUT_A
  //After read OUT_A, start read OUT_B and OUT_N HOPEFULLY

  // free running ADC mode, f = ( 16MHz / prescaler 64 ) / 13 cycles per conversion = 19`231 Hz
  ADMUX = _BV(REFS0) | eva_OUTA //| eva_OUTB;
  ADCSRA = _BV(ADSC) | _BV(ADEN) | _BV(ADATE) | _BV(ADIE) | _BV(ADPS2) | _BV(ADPS1); // | _BV(ADPS0);

 
  //Serial.println("Start to calc zero");

  long midl = 0;
  // get 2 meashurment at 2 sec
  // on ADC input must be NO SIGNAL!!!
  for (byte i = 0; i < 2; i++)
  {
    position = 0;
    delay(100);
    midl += capture[0];
    delay(900);
  }
  zero = -midl/2;

  //Serial.println("Done.");
}



void loop() {

  //Temperature:
  float Temp1 = analogRead(eva_TEMP);
  float Temp2 = Temp1/204.8;
  Temp = (Temp2-570)/2;
  //location on display ???
  //lcd. print(Temp);


  //Button Interupt:
  interrupts();


  //////////////////////signal input
  if (position == FFT_N)
  {
    fft_input(capture, bfly_buff);
    fft_execute(bfly_buff);
    fft_output(bfly_buff, spektrum);

    //peak locate function here
    // Do work

    position = 0;
  }
}


void FLIPPAGE(){
//Flippage pushbutton working function here
}

void RESET(){
//Reset pushbutton working function here
}

Any suggestion will be appreciated. Again, thank you guys.
Logged

Massachusetts, USA
Offline Offline
Tesla Member
***
Karma: 208
Posts: 8821
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

             2: How do I make the ADMUX handle two or more analog inputs? I have looked up thishttp://openenergymonitor.blogspot.com.au/2012/08/low-level-adc-control-admux.html, but still don't know how to implement ADMUX such that it can "catch" two or more analog inputs simultaneously (doable?).

There is only one A/D converter with a multiplexer (ADMUX) to select which pin is connected to the input of the A/D converter.  You can't catch two analog signals simultaneously.
Logged

Send Bitcoin tips to: 1L3CTDoTgrXNA5WyF77uWqt4gUdye9mezN
Send Litecoin tips to : LVtpaq6JgJAZwvnVq3ftVeHafWkcpmuR1e

Global Moderator
Boston area, metrowest
Offline Offline
Brattain Member
*****
Karma: 534
Posts: 26969
Author of "Arduino for Teens". Available for Design & Build services. Now with Unlimited Eagle board sizes!
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

You can add an external ADC that can sample multiple signals simultaneously.
They do cost more.
You will likely find that catching 4 samples sequentially will be fast enough tho.
Logged

Designing & building electrical circuits for over 25 years. Check out the ATMega1284P based Bobuino and other '328P & '1284P creations & offerings at  www.crossroadsfencing.com/BobuinoRev17.
Arduino for Teens available at Amazon.com.

Offline Offline
Newbie
*
Karma: 0
Posts: 3
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

You can add an external ADC that can sample multiple signals simultaneously.
They do cost more.
You will likely find that catching 4 samples sequentially will be fast enough tho.
Can you please guide me how to implement an external ADC? Since this is a FFT operation so I want to make sure the time slot for all signals is the same. So I can't use a simple Analogread().
Logged

Global Moderator
Boston area, metrowest
Offline Offline
Brattain Member
*****
Karma: 534
Posts: 26969
Author of "Arduino for Teens". Available for Design & Build services. Now with Unlimited Eagle board sizes!
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

You connect one up, you read it via SPI commands.

http://ww1.microchip.com/downloads/en/DeviceDoc/21298e.pdf

Here's the way I read 8 inputs & sent it out via serial.
You'll have to write up all the declarations & stuff.
Code:
/*
Every 5mS, read a Pot via SPI, send it via RS232 .
*/
void loop(){
 
  if (millis()>=previousMillis){
  
   previousMillis = previousMillis + 5; // set for next 5 mS interval
  
   // read ADC with 3 byte transfer
   PORTB = PORTB & B11111011;  // ADC_SS, LOW
   // ADCaddress = 0x0600, 640, 680, 6C0, 700, 740, 780, 7C0
   dummyADC = SPI.transfer (highByte(ADCaddress));  // 0x06, 0x07 out, read in dummy data
   highADC = SPI.transfer (lowByte(ADCaddress));    // 0x00, 0x40, 0x80, 0xC0, read in upper 4 bits
   lowADC = SPI.transfer (0);              // dummy 0 byte out , read in lower 8 bits
   PORTB = PORTB | B00000100; // ADC_SS, HIGH
  
   Serial.write (ADCsyncbyte);      // syncbyte = B00110011, 0x33
   Serial.write (address_count);    // find way to put this in top nibble of next command?
   Serial.write (highADC & 0x0F);   // send it out
   Serial.write (lowADC);           // send it out
  
   address_count = address_count +1;  // 0 to 7, pass to Rx for DAC sync - how?
   ADCaddress = ADCaddress + (address_count * 0x40); // update for next pass
  
   if (address_count == 8){
   address_count = 0;
   }  // reset if hit all 8
  
   } // end 5mS test
}
 
« Last Edit: March 15, 2013, 11:33:06 pm by CrossRoads » Logged

Designing & building electrical circuits for over 25 years. Check out the ATMega1284P based Bobuino and other '328P & '1284P creations & offerings at  www.crossroadsfencing.com/BobuinoRev17.
Arduino for Teens available at Amazon.com.

Pages: [1]   Go Up
Jump to: