Pages: [1]   Go Down
Author Topic: Uno: signal sampling at 1 kHz  (Read 915 times)
0 Members and 1 Guest are viewing this topic.
Offline Offline
Newbie
*
Karma: 0
Posts: 2
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

For a project that I'm working on, I need to sample an analog signal at exactly 1 kHz, preferably for 1 or 2 seconds and send the data via serial (well this, among other things, but this is the biggest challenge).  I'm already trying this for a few days, without big success.
My first approach was to write signal to memory and then send the whole array, but the memory of the Uno is not big enough to hold all the 1000 samples (this might be easier to do on an Arduino Mega)....
Another difficulty is to time the loop. Of course there is the delay() function, but with this function, one iteration will certainly take longer then 1 ms. I've tried to overcome this by using the micros() timer in a while loop (thereby reducing the jitter of one iteration).

Probably, I'm in a complete wrong direction and there is something much easier for this...any tips or tricks are welcome!

So far, a snippet of my code is:
Quote
int buf[100]; //the buffer, needs to be size 1000?
unsigned long t0;
unsigned long t1;
int val;

void setup() {
  Serial.begin(9600);
}

void loop() {
  for (int i = 0; i < 100; i++){
    buf = timedLoop(); // fill the buffer
  }
  for (int i = 0; i < 100; i++){
    Serial.print(buf, DEC);
    Serial.print(","); // generate comma-separated values
    Serial.flush(); // make sure all the data is written
  }
}

int timedLoop() {
  t0 = micros();
  val = analogRead(0); //read the signal from AI0
  do
  {
    t1 = micros() - t0;
  } while (t1 < 1000); // execute this while loop for max 1000 micros
  return val;
}

Logged

Global Moderator
UK
Offline Offline
Brattain Member
*****
Karma: 310
Posts: 26633
I don't think you connected the grounds, Dave.
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Code:
Serial.begin(9600);
I'd bump that way up for a start - it takes over 1ms to transmit a single digit at that speed.
Logged

"Pete, it's a fool looks for logic in the chambers of the human heart." Ulysses Everett McGill.
Do not send technical questions via personal messaging - they will be ignored.

Germany
Offline Offline
Faraday Member
**
Karma: 59
Posts: 3091
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

If you reduce resolution (byte)(analogRead(A0) >> 3) you should be able to buffer about 1000 and you can send them easily in binary.

I built a kind of oscilloscope that way ( display 1000 values horizontally and 255 pixel high is sufficient resolution for me)
With standard analogRead I could chould choose the x resolution to anything above 200 ms.

Of course it was not continuous, but just captured 200 ms / 500 ms / 1 sec / 2 sec snapshots.
 
Logged

Global Moderator
UK
Offline Offline
Brattain Member
*****
Karma: 310
Posts: 26633
I don't think you connected the grounds, Dave.
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
If you reduce resolution (byte)(analogRead(A0) >> 3)
Why only seven bits?
Logged

"Pete, it's a fool looks for logic in the chambers of the human heart." Ulysses Everett McGill.
Do not send technical questions via personal messaging - they will be ignored.

Germany
Offline Offline
Faraday Member
**
Karma: 59
Posts: 3091
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
Why only seven bits?
Typo. Thanks.

BTW, I've read that if you type /4, compiler creates a shift operation? 
Logged

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

I'd bump that way up for a start - it takes over 1ms to transmit a single digit at that speed.
If you reduce resolution (byte)(analogRead(A0) >> 3) you should be able to buffer about 1000 and you can send them easily in binary.
OK, two great tips (although the first one was pretty obvious, but I totally overlooked it...).
So far it reduced two problems:
- Buffering the data
- Sending the data

I'm still not sure about the timing thing in a while loop...
Logged

Germany
Offline Offline
Faraday Member
**
Karma: 59
Posts: 3091
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset


Code:
int timedLoop() {
  unsigned long tnow;
  do
      tnow = micros();
  while ( (tnow - t0) < 1000 );  // waits until time has come
  t0 += 1000;
  val = analogRead(0); //read the signal from AI0
  return val;
}

As you increment t0 by the number of micros in a milli (1000 ), you can take any time ( < 1 ms ) for your timedLoop() and don't experience a drift.

 
Logged

Montreal
Offline Offline
Faraday Member
**
Karma: 31
Posts: 2611
Per aspera ad astra.
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

There is TimerOne library, you can set sampling interval exactly at 1 kHz.  Probably, you also don't have to store samples in a buffer, at 115200 kbps you could stream data "real time".
Logged

Seattle, WA USA
Offline Offline
Brattain Member
*****
Karma: 654
Posts: 50931
Seattle, WA USA
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
For a project that I'm working on, I need to sample an analog signal at exactly 1 kHz, preferably for 1 or 2 seconds
You want to do something for one or 2 seconds, 1000 times per second? You need a time stretcher.
Logged

Pages: [1]   Go Up
Jump to: