Go Down

Topic: How to read a 60 Hz sinewave with ARDUINO UNO and Simulink? (Read 305 times) previous topic - next topic

gusmmattos

Hi everyone,

I need to read with ARDUINO UNO a 60 Hz sinewave signal from a waveform generator. It would mean 60 cycles per second. Considering about 100 samples per cycle, I would deal with 6k samples per second.

By using analogRead function, the signal read comes with aliasing. When I took a look into the analogRead function implementation on wiring_analog.c file, I see that a sampling is done and, after each reading, it is sent to the serial port as the return for the analogRead function. I guessed this would take too much computational time, causing the aliasing.

I changed this code so that it reads a bunch of samples and, only then, send them to the serial port. This process keeps repeating. Finally I could read a 60 Hz sinewave signal.

However, at this time, I need to do the same thing for the Analog Input blocks of the Simulink Support Package for Arduino Hardware. I haven't found a similar file to wiring_analog.c related to the Analog Input block, on which I would be able to edit as I did once before.

Is it possible to be done?
Where can I find this file?
Once found, how to edit it so that it would make me pleased?
Is there an easier/other way to solve this problem?

Thank you in advance!

robtillaart

you should set the baudrate of the Arduino to 230400 or 250000 so the sample will be spit out quite fast.

Another option is to work in async mode - I experimented long ago - not tested it with current IDE

Code: (old) [Select]
//
//    FILE: asyncAnalogRead.pde
//  AUTHOR: Rob Tillaart
//    DATE: 09-jun-2012
//
// PUPROSE: experiment 8 bit analogread + fast serial
//
// SEE ALSO: http://www.avrfreaks.net/index.php?name=PNphpBB2&file=printview&t=56429&start=0

#include "wiring_private.h"
#include "pins_arduino.h"

void setup()
{
  Serial.begin(230400);
  Serial.println("start: ");
 
  bitClear(ADCSRA,ADPS0);
  bitClear(ADCSRA,ADPS1);
  bitSet(ADCSRA,ADPS2);
 
  AR_Start(0);
}

void loop()
{
  while(!AR_Ready());
  uint8_t val = AR_Value(); // remove noise
  AR_Start(0);
  Serial.println(val);
}


// uint8_t analog_reference = DEFAULT;

void AR_Start(uint8_t pin)
{
#if defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__)
  if (pin >= 54) pin -= 54; // allow for channel or pin numbers
#else
  if (pin >= 14) pin -= 14; // allow for channel or pin numbers
#endif

#if defined(ADCSRB) && defined(MUX5)
  // the MUX5 bit of ADCSRB selects whether we're reading from channels
  // 0 to 7 (MUX5 low) or 8 to 15 (MUX5 high).
  ADCSRB = (ADCSRB & ~(1 << MUX5)) | (((pin >> 3) & 0x01) << MUX5);
#endif
  // set the analog reference (high two bits of ADMUX) and select the
  // channel (low 4 bits).  this also sets ADLAR (left-adjust result)
  // to 0 (the default).
#if defined(ADMUX)
  ADMUX = (DEFAULT << 6) | (pin & 0x07);
#endif

  // without a delay, we seem to read from the wrong channel
  //delay(1);
  sbi(ADCSRA, ADSC);
}

boolean AR_Ready()
{
  // ADSC is cleared when the conversion finishes
  return bit_is_set(ADCSRA, ADSC)==0;
}

uint8_t AR_Value()
{

  // we have to read ADCL first; doing so locks both ADCL
  // and ADCH until ADCH is read.  reading ADCL second would
  // cause the results of each conversion to be discarded,
  // as ADCL and ADCH would be locked when it completed.
  uint8_t low  = ADCL;
  int high = ADCH;
  // combine the two bytes
  return  low;
}

Rob Tillaart

Nederlandse sectie - http://arduino.cc/forum/index.php/board,77.0.html -
(Please do not PM for private consultancy)

Go Up