Nonsense values from A0 to array

hello, i need to save values from analog0 to int array, so i can catch all those values from analog0 but input them into serial in a slower speed at the same time, because i need to plot those values in node.js web app and the measurement in arduino analog itself is super fast (i have to use 115200 baudRate). The program itself when i’m not saving those values into array works well with no problem and i see AC curve as i should in IDE. but as soon as i try to save them into array i get absolute nonsense values jumping between -20k and 20k or so and i don’t understand why. Right now, with the code i will post here, i’m in point where i see absolutely nothing when i try to plot it in IDE. My guess is there is somethin wrong with memory, but idk, any ideas?

void setup() {
  // put your setup code here, to run once:
  Serial.begin(115200);
  pinMode(8, OUTPUT);
  pinMode(7, OUTPUT);
  pinMode(A0, INPUT);
}

void loop() {
  // put your main code here, to run repeatedly:
  int valArray[10000];
  delay(100);
  digitalWrite(7, HIGH);
  delay(100);
  digitalWrite(8, HIGH);
  for(int i = 0; i < 10000; i++){
      //Serial.println(analogRead(A0)); // THIS WORKS OKAY
      valArray[i] = analogRead(A0);
    }
  for(int i = 0; i < 10000; i++){
      Serial.println(valArray[i]);
      delay(10);
    }
}

what’s your Arduino?
10000 int requires 20k (or 40k bytes) of ram on the stack… that’s a lot … (a UNO has 2k)

if you do this, does it compile?

int valArray[10000];

void setup() {
  // put your setup code here, to run once:
  Serial.begin(115200);
  pinMode(8, OUTPUT);
  pinMode(7, OUTPUT);
  pinMode(A0, INPUT);
}

void loop() {
  delay(100);
  digitalWrite(7, HIGH);
  delay(100);
  digitalWrite(8, HIGH);
  for(int i = 0; i < 10000; i++){
      //Serial.println(analogRead(A0)); // THIS WORKS OKAY
      valArray[i] = analogRead(A0);
    }
  for(int i = 0; i < 10000; i++){
      Serial.println(valArray[i]);
      delay(10);
    }
}

(the compiler will tell you if the global variables are too large)

An interesting problem… JML is pointing you in the right direction, but I’m curious why the fast sampling is so important when there’s going to be a relatively large gap between cycles due to the serial upload…

Uno has 2000 bytes of SRAM memory, Mega has 8000 bytes of memory, 1284P has 16000 bytes of memory. 100000 int’s need 20000 bytes.

Hmm - no compiler warning!
“Global variables use 188 bytes (9%) of dynamic memory, leaving 1860 bytes for local variables. Maximum is 2048 bytes.”

But you do get one if valArray[10000] is made global by declaring it before setup()
“Global variables use 20188 bytes (985%) of dynamic memory, leaving -18140 bytes for local variables. Maximum is 2048 bytes.
Not enough memory; see http://www.arduino.cc/en/Guide/Troubleshooting#size for tips on reducing your footprint.
data section exceeds available space in board
Error compiling for board Arduino Uno.”

1 Like

If you make your array size 500, then run your “for” loop for 500 iterations, then this will be the exact amount of data points to display one full screen on the Serial Plotter.

Assuming your AC frequency is 50Hz…this is 20ms or 20,000µs.
On an Uno, the time analogRead takes for 500 readings is about 100µs x 500 = 50,000µs.
So the plot will show about 2.5 cycles.

If you want to zoom in on the waveform, just add a small delay after you take each reading. For example, to view 1 cycle, you’ll need to fill in the extra 30,000µs / 500 = 60µs. (delay between readings). So just add delayMicroseconds(60); after you capture each reading.

1 Like

reducing my array size seem to fix this problem. even though there is a slight pause between the main loop iterations, that can make a weird triangle out of a round waveform at some places. but it’S definitely better than nothing. Next thing i’ll need to do, is to create functions with different digital pin combinations so i can switch between those combinations through web server. Thanks alot for help :slight_smile: as for a lastchancename question, i don’t really have a problem with the sampling being fast, i’m just making application, and slowing down the sampling through loop with delay is more of a comfort thing for the user so he doesn’t have a super fast flashing plot infront of him. Aand I tried node.js to serial communication at 115200 before and it’s not very convenient for viewing data at this rate, so i have to slow it down.

I’m still unclear why you acquire stuff in an array to spit it out later in one go if you need to constantly monitor a stream

print will block when you’ve filled the output buffer, so that’s going to be your limiting factor. You should set the Serial line at 2,000,000 bauds if the other side is a modern computer that will create less of a lag

you can use millis() to pace the acquisition

void setup() {
  Serial.begin(2000000); // go as fast as your Serial line can go to not block the code if possible
}

void loop() {
  static unsigned long lastChrono;
  unsigned long currentChrono = millis();
  if (currentChrono - lastChrono >= 10) { // ~100Hz
    Serial.println(analogRead(A0));
    lastChrono = currentChrono;
  }
}
1 Like

Your code works better than mine, thanks! I just used my approach because i’m not that good in coding with arduino and i had no idea i could do something like you did. It’s just something that came up in my mind first. But could you explain a bit how does the code work? i don’t think i’m entirely sure what it does…

I check in the loop if 10ms have elapsed since the last acquisition (and print), and if so I proceed to perform a new acquisition and update my variable lastChrono with the current time.

See the blink without delay example and For extra information and examples look at Using millis() for timing. A beginners guide and Several things at the same time

1 Like

great, thanks alot!