0

I have an array of numbers that will be subtracted from the ADC readings of a 50 Hz sine wave. Using Serial.begin(57600);, I can only output 25 samples per sine wave cycle, or about 1,250 samples per second. my questions are:

  1. how fast the increent of array number moves with y++ in my int sinus[]? because when i see on serial monitor with 52700 baudrate it can only show about 25 numbers per cycle (50Hz)
  2. how to increase the speed the increment of y++ in my array?
int sinus[] = {
    70, 72, 83, 92, 108, 132, 157, 182, 207, 230, 243, 255, 255,
    255, 250, 238, 217, 193, 169, 143, 118, 98, 88, 77, 72, 80
};
int dataSensor;
int hasil[26];
int datasensor2;
int dataBaru;
int x;
int y;
int intPin = 2;
int output;
int output2;
int toggle;
int toggle2;
int z;

void setup() {
    TCCR1A = 0b00000010;
    TCCR1B = 0b00011100;
    TCCR0A = 0;  //disable millis, delay and mciros
    TCCR0B = 0;
    ICR1 = 3200;

    Serial.begin(57600);

    pinMode(A1, INPUT);
    pinMode(A0, INPUT);
    pinMode(A2, INPUT);
    pinMode(intPin, INPUT);
    pinMode(9, OUTPUT);
    pinMode(10, OUTPUT);

    attachInterrupt(0, genJeah, RISING);
}

void genJeah() {  //intrupsi rising
    y = 5;
}

void loop() {
    dataSensor = analogRead(A0);
    toggle     = digitalRead(A1);
    toggle2    = digitalRead(A2);
    dataBaru = map(dataSensor, 0, 1023, 0, 255);

    for (x = 0; x < 25; x++) {
        hasil[x] = sinus[x];
    }
    // for (x=0; x<100; x++){

    output = sinus[y] - dataBaru;
    Serial.println(output);
    y++;
    if (y > hasil[26]) {
        y = 0;
    }
}
  • what does move number mean? – jsotola May 3 at 3:45
  • 1
    would raising the serial speed to 230400 help? - 57600 outputs 5760 characters per second, so even if you output a single character as fast as possible, you wont make 5760 "data points" per second (the reason you only get about 2500 per second is that you output an average of 2.3 digits per "output" – Jaromanda X May 3 at 4:42
  • Another possibility of raising speed is sending byte data instead of ASCII data. Would that be acceptable? – chrisl May 3 at 6:21
  • I edited the title and the body of your question to make it clearer. I believe my rewriting faithfully reflects what you intended to write, but feel free to re-edit if I misinterpreted something. Note that, for the purpose of your question, the fact that you are subtracting values from an array is completely irrelevant. Ideally you should remove this part (and the corresponding code) from the question in order to keep it focused on one single problem. Unless the question is about a compile error, you should also make sure, before posting some code, that it does at least compile. – Edgar Bonet May 3 at 7:51
  • 3
    Arduino @ 16Mhz with AVR MCU can at most perform 8.9 K ADC sample/s (10-bits, 112 us). This assumes the same channel (pin). Changing analog pin takes additional time. The upper limit for the sketch is approx. 1 K sample/s just for the ADC (10-bits). The conversion from integer to string to print takes additional time but ADC can be run in parallel. Also the ADC can be initiated for 8-bit conversion instead. – Mikael Patel May 3 at 8:45
2

If you are looking for throughput then stop sending the ASCII conversion of numbers and just send the numbers. In other words, use Serial.write() rather than Serial.print(): you can send ~25k integers per second with a 52k baudrate.

As you are actually remapping the ADC output to a single byte, that means you can easily achieve a 48k/s throughput with this simple change.

If you are also looking for low latency please consider the USB connection is actually packet based, not stream based, which means you will receive the data in chunks, no matter how frequently you write. You can speed it up a bit flushing the channel, at the cost of throughput.

  • will it work with Serial Plotter? – Juraj May 3 at 8:43
  • Do you mean the plotting view included in Sloeber? – Roberto Lo Giacco May 3 at 8:46
  • Arduino IDE has Serial Plotter too – Juraj May 3 at 9:16
  • Sorry, wasn’t aware of that. For the Sloeber one I wrote a library (PlotPlus) which can probably achieve the 10k/s throughput considering the 2 additional protocol bytes used. I’m not sure it is compatible with the Arduino IDE one, never tried myself – Roberto Lo Giacco May 3 at 9:20
  • doesn't Serial Plotter read numbers as text? – Juraj May 4 at 4:04
0

how fast the increment of array number moves with y++ in my int sinus[]?

Incrementing an int is fast enough. Even on a slowish Uno, y++ will take less than one microsecond to execute, so you can do it a million times per second if you want...

when i see on serial monitor with 52700 baudrate it can only show about 25 numbers per cycle (50Hz)

Your loop() is doing more than y++, no it's no wonder it takes more time!

There are two slow functions there:

  • analogRead() takes about 110 µs

  • Serial.println() is initially fast, but once the output buffer is full, it runs at the speed of the serial port.

The limiting factor here is Serial.println(). You are printing 4.6 bytes on average per sample (2.6 printable characters, plus CR and LF). Each byte is worth 10 bits on the wire (one start bit, 8 data bits and one stop bit). That is 46 bits per sample at 57,600 bits per second. The ratio of these numbers gives the 1,250 samples per second you experienced.

how to increase the speed the increment of y++ in my array?

It's very hard to answer this question because you did not explain what you are actually trying to achieve. If I naively take the question at face value, the simplest option is to just repeat y++ several times per loop iteration:

y++;
y++;
y++;
y++;

This can obviously be optimized into

y += 4;

and the compiler may even be able to figure out this optimization by itself.

But maybe what you don't care so much about speeding up y++, and instead you want to process more data samples per second? If this is the case, then you can speed up the loop by speeding up the serial port:

Serial.begin(115200);

by printing only every other sample (or one sample every N):

static bool print_this_sample;
if (print_this_sample) {
    Serial.println(output);
}
print_this_sample = !print_this_sample;

by printing one sample every so often:

static uint32_t last_print_time;
if (millis() - last_print_time >= PRINT_PERIOD) {
    last_print_time += PRINT_PERIOD;
    Serial.println(output);
}

by printing the samples in binary (first make sure they fit in a byte):

Serial.write((byte) output);

Now, what I suspect, is that you actually want to get your processing synchronized with the 50 Hz mains. If this is the case, you will have to completely rethink your program, and reason about the timings: at what specific time do you want to take each sample? The Arduino timing functions (millis() and micros()) should help.

As you see, half of this answer is me making guesses about what you may want to achieve. This is a sign of a very badly written question. Normally it is your job to explain that in detail. Please, rewrite the question and provide all the necessary background to help us understand your project, and the difficulties you are facing.

  • Might want to add that the number conversion will take several hundred micro-seconds as it involves integer division. – Mikael Patel May 7 at 11:03
  • thanks, again its very great explanation – john caren May 7 at 14:05

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.