message:
How to read from and write to rs232 device from/to Arduino

I would like to read data from a rs232 device (SL-5868P Sound Level Meter).
protocol and more : https://sigrok.org/wiki/Colead_SL-5868P.

I already have a Python script to read the data with a TTL to USB converter (without Arduino). Now I also want to be able to read the meter via the Arduino.

I've bought a RS232 to TTL Converter (MAX3232). I get either very weird characters (baud rate set correctly), or not logical numbers. With the MAX chip I get no data at all.

1. To see if there is data ready, 0x10 must be sent by the meter.
2. To get the data, send 0x20.

Would someone be willing to help me out a bit? That would be really nice. Maybe there is someone who has experience with reading (and writing to) RS232. The only thing that matters is how I can retrieve the data. I know the rest what needs to be done with software (conversion, etc.). I'm not that familiar with Arduino's .

The code below is an example from SoftwareSerial (a little bit modified). I'm using the Arduino Uno.

    #include <SoftwareSerial.h>

    SoftwareSerial mySerial(10, 11); // RX, TX

    void setup() {
      // Open serial communications and wait for port to open:
      Serial.begin(2400);
      while (!Serial) {
        ; // wait for serial port to connect. Needed for native USB port only
      }

      Serial.println("Goodnight moon!");

      // set the data rate for the SoftwareSerial port
      mySerial.begin(2400);
    }

    void loop() { // run over and over
      if (mySerial.read() == 0x10) {
        //mySerial.write(0x20);
        Serial.println("Data available");
        Serial.println(mySerial.read());
      }

      if (Serial.available()) {
        mySerial.write(Serial.read());
      }
      //delay(300);
    }

And the current schematic (sorry for my drawing skills)

[![enter image description here][1]][1]

  [1]: https://i.stack.imgur.com/WGGEe.png

body:
You didn't show how you connected the MAX3232, so I cannot say anything about that. But I can write something about your code and how the data gets received on the PC.

- **On the PC:** Here it is important how you are reading the serial data on the PC. The Serial Monitor for example expects ASCII encoded text. It cannot correctly display binary data. That is the reason, that you get weird characters with the correct baudrate. The data is correctly received, but it doesn't represent ASCII characters. It is just binary data and interpreting it as ASCII characters will not make any sense.

    Also it just sends ASCII encoded text, no binary data. So when you are sending "10" it will send the bytes `0x31` and `0x30`, plus any line ending, that you have selected (`\n` aka `0x0A` if you selected newline as line ending). As your device speaks in binary data you might wanna speak binary to it. So you either need to decode the ASCII data on the Arduino, before sending it to the device, or you need to use a different serial program, which can handle binary data.

- **Your code:** First look at this line

        Serial.println(mySerial.read());

    Here you are reading exactly **one byte** from the SoftwareSerial interface and then you are printing it. `Serial.read()` or `SoftwareSerial.read()` only read one single byte from the buffer, but the data from your device spans over multiple bytes, as described on the wiki page, that you linked. Look at the table titled "Data structure". The returned data consists of 10 bytes in total (numbered from 0 to 9), where bytes 3 to 7 contain the actual data. The rest gives configuration and status data, a header as packet start and a checksum to check for transmission errors. So reading only one byte isn't enough you need to read all of them.

    Then you are `Serial.print()`ing the data. The `print()` function and its siblings are formatting the data human readable. That might help you here, but you need to make sure, that the resulting output is really readable for you, especially when you are reading multiple bytes (as you need to do, as explained above). Here you need to make a decision: Either

    * you could decode and format the binary data from the device on the Arduino and send the human readable format over Serial
    * or you could send the binary data straight to the PC and decode it there with a fitting program (either a Serial program, which can handle binary data, or your own program, for example with python or processing)

    If you go the first way, you should first read the different parts of the message and then print these parts with additional text, that explains, what data means what. Otherwise you would have just a long line of numbers, which are also rather difficult to read. Also you might wanna decide on a number base. I think only decimal or hexadecimal are really relevant here. For that you could use `Serial.print(value, DEC)` or `Serial.print(value, HEX)`, which tells the Serial library to use the specified number base.

    **Now about the actual data format:** The data format is described with

    > BCD-encoded value, one byte per digit 0x00-0x09. 0x0a means ignored digit. The last digit represents the decimal.

    on the linked wiki site. So while this is still binary data (not ASCII encoded), each byte represents a decimal digit of the actual value. You could decode it accordingly. So I guess a byte sequence of `0x01 0x00 0x02 0x09 0x07` would mean `1029.7`. As you wrote, that you already know how to convert the data, I will not go deeper about this here.

    And lastly you need to rethink your program structure. The workflow with your device is the following:

        Arduino waits for device to send data ready byte (0x10)
        device sends 0x10
        Arduino sends 0x20 (command to send data)
        Arduino waits for device to send at least 10 bytes of data
        device sends a complete data packet with 10 bytes
        Arduino interprets the data in the received packet and acts accordingly
        repeat

    You need to follow this workflow and also anticipate, that the data transmission takes some time (especially at the really slow 2400 baud). For this a Finite State Machine (FSM) is a good fit (there are many extended descriptions about FSMs on this site, for example my answer to [this question][1] or [this question][2], though there are many more, which you just need to search for). We just track at which part of the workflow we are currently and execute the according code. Something like this:

        enum ReceiveState {IDLE, RECEIVING};
        ReceiveState rec_state = IDLE;

        void loop(){
            if(mySerial.available()){
                switch(rec_state){
                    case IDLE:
                        if(mySerial.read() == 0x10){
                            // data is ready, command to send data
                            mySerial.write(0x20);
                            // change state to receiving
                            rec_state = RECEIVING;
                        }
                        break;
                    case RECEIVING:
                        if(mySerial.available() >= 10){// only read data, if a full packet was received, at least 10 bytes
                            // Here you need to decode the binary data and handle it accordingly (for example printing in the wanted format)
                            // Reset rec_state afterwards to be ready for the next time, that data is ready to read
                            rec_state = IDLE;
                        }
                        break;
                    }
                }
            }
        }

    That might seem like a bit of overkill, but the concept is very important in the Arduino world and it is very powerful. Also it makes it easier to accommodate workflow structures.

  [1]: https://arduino.stackexchange.com/questions/70544/how-do-i-repeat-else-if-cmd-3-until-i-press-another-cmd/70545#70545
  [2]: https://arduino.stackexchange.com/questions/63488/wanted-to-control-2-servos-with-serial-read/63491#63491


sender: user

sender: assistant

body:
Hi and welcome to the wonderful world of Arduino. It appears that you have picked-up Arduino with ease. Your program is almost there. Your wiring connection diagram looks to be correct.

When I am doing a project like this, I won't write my full application first. Instead I write a series of test programs to make sure each chunk is performing exactly as I want it to.

I would start by writing a program that just passes the serial information recieved from the Sound Level Meter and displays it on the serial monitor. Something similar to this:

    #include <SoftwareSerial.h>

    SoftwareSerial mySerial(10, 11); // RX, TX

    void setup()
    {
      // Open USB serial communications
      Serial.begin( 2400 );
      Serial.println("USB Serial is up and running");

      // set the data rate for the SoftwareSerial port
      mySerial.begin( 2400 );
    }

    void loop()
    {
      if ( mySerial.available() )
      {
        // Write the serial from the S.L.M. to the USB (debug) serial port
        Serial.write( mySerial.read() );
      }

      if ( Serial.available() )
      {
        // Write the serial from the USB (debug) serial port to the S.L.M.
        mySerial.write( Serial.read() );
      }
    }

This program should be enough to communicate with the Sound Level Meter. But this leads me to my first concern - choice of serial monitor.

While the Arduino built in serial monitor is adequate it is only really good for sending/recieving text. (Plus it sends a CR/LF every time you hit enter.) I can see straight away that you require to send/recieve hex numbers. Hex numbers won't display well on the serial monitor.

Instead I prefer to use a terminal program by "der-hammer" called [hterm][1]. ([Screenshot here][2]). It lets you view the input in ASCII, hex, bin and decimal. Likewise it lets you send ASCII, hex, bin and decimal or a mixture of each. When sending information, you can configure it so that it finishes the data with either a line feed, a carriage return, both or none.

By the sound of it, you don't want a CR or LF at the end of the data you send. So in the "Input Options" set the "Send on enter" to "None".

For the recieved data, you need to view that in hex so make sure the "hex" box is checked just above the recieved data. (Uncheck "ASCII".)

You could create a loop-back test by removing the Sound Level Meter and instead link the RS232 Rx to the RS232 Tx. This will allow you to see on hterm exactly what the Sound Level Meter sees when you send data.

----

**Issues with your program**

      if (mySerial.read() == 0x10) {
        //mySerial.write(0x20);
        Serial.println("Data available");
        Serial.println(mySerial.read());
      }

The section of code will only read one byte of data after it has detected `0x10` (See the [Serial.Read() reference page][3]). Anything more than that will get consumed by the next time the `if` statement checks the serial line for `0x10`.

I notice in the line `Serial.println(mySerial.read());` that you are reading the data in (which is in hex format) but then trying to write it out in ASCII by using the `println()` function. This will not give you the output you desire.

Also, after detecting `0x10` it reads the software serial line for one more byte - meaning if there is nothing following the `0x10` then the `mySerial.Read()` command will hang for 1s until it timeouts.

    if (Serial.available()) {
      mySerial.write(Serial.read());
    }

As others have pointed out, using the serial monitor will send this as ASCII characters (and include a CR/LF character(s)) instead of the hex value that you want. Kudos is given to you, that you chose `mySerial.write()` instead of `mySerial.println()`.

----

**My Take on Your Program**

*The follwoing code is untested.*

    #include <SoftwareSerial.h>

    SoftwareSerial mySerial(10, 11); // RX, TX

    void setup()
    {
      // Open serial communications and wait for port to open:
      Serial.begin(2400);
      // The wait for serial port to connect is not needed for Arduino Uno
      Serial.println("USB Serial is up and running");

      // set the data rate for the SoftwareSerial port
      mySerial.begin(2400);
    }

    void loop()
    {
      if ( mySerial.available() )
      {
        int recievedByte = mySerial.read();
        Serial.write(recievedByte);    // Send to USB serial - assuming using hterm in hex
        if ( recievedByte == 0x10 )
        {
          mySerial.write(0x20);
        }
      }

      // You could remove the following code - data must be in hex.
      if ( Serial.available() )
      {
        mySerial.write(Serial.read());
      }
    }

  [1]: http://der-hammer.info/pages/terminal.html
  [2]: https://www.der-hammer.info/terminal/bilder/term_071linux_large.png
  [3]: https://www.arduino.cc/reference/en/language/functions/communication/serial/read/


message:
How to switch HC-05 from DATA mode to AT mode?

I am asking how to enter from the data mode to the AT command mode without restarting and disconnecting any power supply. In other words, I am trying to make a driver to handle HC-05 module and now I have to switch between DATA mode to AT mode. When I try to switch backwards, it worls ( by putting off the EN pin and then send “AT+RESET” ) but from DATA mode to AT Mode I can’t reset the module. Anyhelp please ?

body:
I am pretty certain there is no way to enter command mode from data mode without resetting the whole module.  The only way to enter command mode is by setting the KEY pin high, and that pin is only read during the initialization phase of the module - and that means either a power cycle / reset, or a command-initiated reset.

You could either:

* Provide a power control circuit which turns the module on and off (MOSFETs are good for this), or
* Modify the module to attach a wire to pin 11, the RESET pin, and pulse that LOW to reset into command mode (I assume LOW, since that's the most common, though I haven't found anything to confirm it yet).


message:
How do I temporarily disable TIMER5 Interrupts?

I have a fairly complex autonomous robot program that is getting into trouble when executing controlled turns.  I constructed a very small program to test just the turns, and this works fine.  When I port the turn algorithm into the main program, however, it behaves erratically, and I suspect the culprit is a TIMER5 interrupt ISR that is in the main program but not in the test program.

To troubleshoot, I added the TIMER5 ISR code to the test program, and I want to be able to enable and disable the ISR using keyboard commands, to see if I can cause the anomalous behavior with the ISR enabled, and prevent it by disabling the ISR.

From reading about TIMER interrupts, it appears that setting TIMSKx (TIMSK5 in my case) to 0 will disable the ISR, and setting bit 0 to 1 (using TIMSKx |= OCIExA) will enable it. I have a 'CheckForUserInput()' routine which allows me to input commands from the keyboard, so I added a 'T' command, as follows:

    switch (incomingByte)
    {
    case 0x54: //ASCII 'T'
    case 0x74: //ASCII 's'
     Serial.println(F("Toggle TIMER5 Enable/Disable"));
     if (TIMSK5 == 0)
     {
      Serial.println(F("Enable TIMER5"));
      TIMSK5 |= OCIE5A;
      mySerial.printf("TIMSK5 = %x\n", TIMSK5);
     }
     else
     {
      Serial.println(F("Disable TIMER5"));
      TIMSK5 = 0;
      mySerial.printf("TIMSK5 = %x\n", TIMSK5);
     }
     break;

I have an LED set up to blink each time the ISR fires, and I can see that I can stop the ISR from firing reliably with the first 'T' input, but I can't reliably restart it with the second 'T' command, even though I can tell from the printouts that the proper piece of code executed, like in the following output

    Opening port
    Port open

    Checking for MPU6050 IMU at I2C Addr 0x69
    MPU6050 connection successful
    Initializing DMP...
    Enabling DMP...
    DMP ready! Waiting for MPU6050 drift rate to settle...
    MPU6050 Ready at 0.52 Sec
    End of test - Stopping!
    I received: 63
    ENTERING COMMAND MODE:
    0 = 180 deg CCW Turn
    1 = 180 deg CW Turn
    A = Back to Auto Mode
    S = Stop
    F = Forward
    R = Reverse

           Faster
     8
    Left 4 5  6 Right
     2
           Slower
    Got D
    Got A
    Got 74
    Toggle TIMER5 Enable/Disable
    Disable TIMER5
    TIMSK5 = 0
    Got D
    Got A
    Got 74
    TEnabling DMP...
    DMP ready! Waiting for MPU6050 drift rate to settle...
    MPU6050 Ready at 0.52 Sec
    End of test - Stopping!
    I received: 63
    ENTERING COMMAND MODE:
    0 = 180 deg CCW Turn
    1 = 180 deg CW Turn
    A = Back to Auto Mode
    S = Stop
    F = Forward
    R = Reverse

           Faster
     8
    Left 4 5  6 Right
     2
           Slower
    Got D
    Got A
    Got 74
    Toggle TIMER5 Enable/Disable
    Disable TIMER5
    TIMSK5 = 0
    Got D
    Got A
    Got 74
    Toggle TIMER5 Enable/Disable
    Enable TIMER5
    TIMSK5 = 1
    Got D
    Got A

I'm sure I'm doing something wrong in the way I am attempting to re-enable the TIMER5 ISR, but I really can't see it.  Anyone have a clue?

TIA,

Frank

body:
You wrote:
> ```c++
> TIMSK5 |= OCIE5A;
> ```

You mean

```c++
TIMSK5 |= _BV(OCIE5A);
```

or, equivalently,

```c++
TIMSK5 |= 1 << OCIE5A;
```


message:
Average of 10 readings, wrong

I am reading from loadcell and calculating the average of last 10 readings. But when the load cell reads something more than 3800 g the average gets negative, how? The mass I read are not negative numbers. I have been trying to find my mistake but I am not able to. Any help?

```
#include "HX711.h"

const int numReadings = 10;
const int LOADCELL_DOUT_PIN = 8;
const int LOADCELL_SCK_PIN = 10;
int readings[numReadings];      // the readings from the analog input
int readIndex = 0;              // the index of the current reading
int total = 0;                  // the running total
int average = 0;                // the average
int mass  =0;
long reading = 0;

HX711 scale;

float a = 0.0088;
float b = 2009.7;

void setup() {
  // initialize serial communication with computer:
  Serial.begin(9600);
  // initialize all the readings to 0:
  for (int thisReading = 0; thisReading < numReadings; thisReading++) {
    readings[thisReading] = 0;
  }
  scale.begin(LOADCELL_DOUT_PIN, LOADCELL_SCK_PIN);
}

void loop() {
  if (scale.is_ready()) {
    // read from the sensor:
    reading = scale.read();
    // convert to mass
    mass = int((a*reading)-b);
    // subtract the last reading:
    total = total - readings[readIndex];

    Serial.print(int((a*reading)-b));
    readings[readIndex] = mass;
    // add the reading to the total:
    total = total + readings[readIndex];
    // advance to the next position in the array:
    readIndex = readIndex + 1;

    // if we're at the end of the array...
    if (readIndex >= numReadings) {
      // ...wrap around to the beginning:
      readIndex = 0;
    }

    // calculate the average:
    average = total / numReadings;
    // send it to the computer as ASCII digits

    Serial.print("   ");
    Serial.print(average);
    Serial.println("");
    delay(1000);        // delay in between reads for stability
  }
  else{
    Serial.print("loadcell not found!");
  }
}
```

body:
As already commented by Majenko, the problem in integer wraparound. One solution would be to get rid of that `total` variable and calculate every new average based on the previous average and the mass you are replacing in the array, using this formula:

    new_average = old_average + (mass - readings[readIndex]) / numReadings

So your code would look like:

      if (scale.is_ready()) {
        // read from the sensor:
        reading = scale.read();
        // convert to mass
        mass = int((a*reading)-b);

        // calculate the new average:
        new_average = average + (mass - readings[readIndex]) / numReadings;

        Serial.print(int((a*reading)-b));
        readings[readIndex] = mass;

        // advance to the next position in the array:
        readIndex = readIndex + 1;

        // if we're at the end of the array...
        if (readIndex >= numReadings) {
          // ...wrap around to the beginning:
          readIndex = 0;
        }

        // set the average:
        average = new_average;

        // send it to the computer as ASCII digits
        Serial.print("   ");
        Serial.print(average);
        Serial.println("");
        delay(1000);        // delay in between reads for stability
      }

Just don't forget to add a declaration for `new_average` to the beginning of your code.


body: Another option would be use 'long' as a variable type for total.   Depending on your application, you also might look into an exponentially weighted moving average (EWMA); it can de-emphasize older data points, if that is an issue.


message:
Error trying to simulate temperature dynamically

I'm trying to simulate dynamic temperature using a small set of data with ESP32. I've just realized that the relay doesn't change the status if there is some variation of the temperature upper or lower the threshold.

If the temperature starts below the modeled temperature, the relay will turn on but, once it reaches the model's temperature or exceeds it, the status doesn't change, and the system will warm up till the next model.

Am I missing something in my code?

    #include <OneWire.h>
    #include <DallasTemperature.h>
    #include <NTPClient.h>
    #include <WiFi.h>
    #include <WiFiUdp.h>

    WiFiUDP ntpUDP;

    NTPClient timeClient(ntpUDP, "europe.pool.ntp.org", 7200, 60000); //UTC+1 (Europe)

    unsigned long current_time;

    #define WIFI_AP "xxxxx"
    #define WIFI_PASSWORD "xxxxx"
    //WiFi SETUP
    WiFiClient wifiClient;
    int status = WL_IDLE_STATUS;
    unsigned long lastSend;

    const int oneWireBus1 = 0;
    OneWire oneWire1 (oneWireBus1);
    DallasTemperature sensors1 (&oneWire1);

    const int relay1 = 02;

    struct SetPoint {
      unsigned long time;
      float temperature;
    };

    #define DATA_SIZE  17

    SetPoint scen1[DATA_SIZE] = {
      {1622652330,26.97},//18h
      {1622652390,25.62},
      {1622678400,24.87},
      {1622689200,24.16},
      {1622700000,23.86},
      {1622710800,25.17},
      {1622721600,26.41},
      {1622732400,27.22},
      {1622743200,26.78},
      {1622754000,25.83},
      {1622764800,25.1},
      {1622775600,24.6},
      {1622786400,24.24},
      {1622797200,26.81},
      {1622808000,29.35},
      {1622818800,29.38},
      {1622829600,30.5}
    };

    unsigned int pos = 0;

    void setup() {
      Serial.begin(115200);
      sensors1.begin();
      pinMode(relay1, OUTPUT);
      InitWiFi();
      lastSend = 0;
      timeClient.begin();

    void loop() {

      sensors1.requestTemperatures();
      float temperature1 = sensors1.getTempCByIndex(0);

      timeClient.update();

      long current_time =  timeClient.getEpochTime();

      if (pos < DATA_SIZE && current_time >= scen1[pos].time) {
        if (temperature1 < scen1[pos].temperature) {
          digitalWrite (relay1, HIGH);
        }
        else if (temperature1 > scen1[pos].temperature) {
          digitalWrite (relay1, LOW);
        }
        pos++;
      }

      Serial.println(timeClient.getEpochTime());
      Serial.println(timeClient.getFormattedTime());
      Serial.println(pos);
      Serial.println(scen1[pos].temperature);
      Serial.println(scen1[pos-1].temperature);
      Serial.print("Temperature Censius - Sensor 1: ");
      Serial.print(temperature1);
      Serial.println(" ºC ");
      delay(3000);

    }

(UPDATE)

Replacing the first `if` with `while` doesn't change anything.

The code works when taking `if` / `else if` out of nested `if`, but in this case I'm not able to increase time (the `pos++` is also commented), and define limits according to the array size.

    //  if (pos < DATA_SIZE && current_time >= scen1[pos].time) {
        if ((temperature1 < scen1[pos].temperature)&& (current_time >= scen1[pos].time)) {
          digitalWrite (relay1, HIGH);
        }
        else if ((temperature1 > scen1[pos].temperature)&&(current_time >= scen1[pos].time)) {
          digitalWrite (relay1, LOW);
        }
    //    pos++;
    //  }

body:
I have to remove the `pos++` from if statement to have digitalWrite working again according to captured temperature:

      if (pos < DATA_SIZE && current_time >= scen1[pos].time) {
        if (temperature1 < scen1[pos].temperature) {
        digitalWrite (relay1, HIGH);
        }
        else if (temperature1 > scen1[pos].temperature) {
        digitalWrite (relay1, LOW);
        }
       }

Obviously this isn't updating time and the system gets stuck at time 0 of the array.

(UPDATE)

As well observed by Dave Newton, the previous observation is pointless to really fix the problem.

The problem was fixed taking the `if` statement that control the relay from inside the one controlling the time.

Now I can simulate a time interval defined with the array and use the temperature (also present in the array) to turn on/off the relay that controls the heater and simulates environment temperature:

First I created a function that will work as a thermostat:

    void set_thermostat() {
      sensors1.requestTemperatures();
      float temperature1 = sensors1.getTempCByIndex(0);

      if (temperature1 < scen1[pos].temperature) {
        digitalWrite (relay1, HIGH);
      }
      else if (temperature1 > scen1[pos].temperature) {
        digitalWrite (relay1, LOW);
      }
    }

Then I can it at the `loop` function, outside the statement that increases the time, based on the one defined by the array:

      if (pos < DATA_SIZE && current_time >= scen1[pos].times) {
        pos++;
      }

      set_thermostat();

This reproduces exactly what I've been looking for, with real-time control of the temperature comparing the environmental one with the model.


message:
Measuring the battery level powering the arduino

I would like to power my arduino nano with a 9V battery, but I would also like to measure the voltage of the battery to know its charge level.
Can I use the [MAX471 Voltage Current Sensor][1] module by connecting the VIN pin to my battery and VOUT to my arduino ?

  [1]: https://aliexpress.com/item/32672702701.html?src=google&albch=shopping&acnt=248-630-5778&isdl=y&slnk=&plac=&mtctp=&albbt=Google_7_shopping&aff_platform=google&aff_short_key=UneMJZVf&&albagn=888888&isSmbAutoCall=false&needSmbHouyi=false&albcp=10191220517&albag=107473525088&trgt=743612850874&crea=fr32672702701&netw=u&device=c&albpg=743612850874&albpd=fr32672702701&gclid=Cj0KCQjw2NyFBhDoARIsAMtHtZ60kZjqZf6Pn0b21O_8pnOQl4r2uiEo-iRub2k4lLdjbPr-t_sww7MaAvAQEALw_wcB&gclsrc=aw.ds

body: If you want measuring a "battery level" in mAh for example, you must measure Voltage AND Current, so INA219 is a better deal (it is a I2C control).


message:
How can i draw an electronic diagram of this?

[![How can i draw a diagram out of this?][1]][1]

  [1]: https://i.stack.imgur.com/ohTYt.png
I need help to draw a diagram of this picture
the project include an Arduino nano, dht11 sensor, power module IRF520, 12V power supply and a fan

body:
See [Rules and guidelines for drawing good schematics](https://electronics.stackexchange.com/q/28251/2191) on electronics.stackexchange.com.

I'm no expert but perhaps some of what I have found will be of help.

To produce a clear easy-to-read useful schematic it doesn't really matter what tools you use. This website has a reasonable schematic editor so I suggest you could try that to start with.

Other tools I have tried include KiCAD, EasyEDA and Fritzing. KiCAD is maybe a bit hard to start with and Fritzing I find is very troublesome - It's good for the kind of breadboard layout diagram it was originally designed for. I have really enjoyed using EasyEDA. Other notable tools include Eagle. All these are free or have free versions for hobbyists. Beyond that are more capable and sophisticated professional tools.

Drawing a good schematic is an art and taking care of small details makes a big difference to how useful the diagram is.

The main features that I find make schematics for me to read are

- Ground connections at bottom edge of diagram.
- Positive voltage connections at top edge of diagram.
- Left to right flow for signals and power (e.g. battery at left, microprocessor in middle, LEDs, motors etc at right)
- Avoid having wires cross. Adjust the pin positions on an IC symbol to make this possible.
- Label everything clearly but don't let text overlap with anything else.

<!-- Begin schematic: In order to preserve an editable schematic, please
     don't edit this section directly.
     Click the "edit" link below the image in the preview instead. -->

![schematic](https://i.stack.imgur.com/0RdSj.png)

<!-- End schematic -->

The way you appear to be powering these modules seems a bit eccentric but this would be how I might draw that as a block-level schematic.


message:
Where are the programatic definitions for different processors stored?

I need to modify an existing library that relies on being able to detrmine what board / processor the code is being run on. To do this, it uses definitions such as this for an Arduino Mega:
```cpp
// Arduino Mega
#elif defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__)
```
I need to update the library for a further 2 boards, namely the Raspberry pi pico (mbed os) and the Robotis OpenCR.

I can't seem t find where the processor name is actually defined. If someone could point me in the right direction, that would be great. Thanks.

Edit:
If anyone knows what the equivelent define is for the raspbery pi pico - rp2040, that would be fantastic!

body:
They are defined by the compiler itself, and based on the name of the microcontroller passed to the compiler as (for AVR GCC) `-mcpu=<mcu name>`.

You can list the defines for a version of GCC using (for example for AVR gcc):

```
avr-gcc -mmcu=atmega328p -dM -E - < /dev/null
```

Not sure what you'd use on Windows for `/dev/null`. Different target compilers use different flags to define the MCU, and you of course need to know the MCU the board uses to pass to the compiler.

You will have to investigate what relevant flags are passed to the compiler for your desired chips, and you can find those by looking in the platform.txt file for the core associated with the board.


message:
I need help with my final year project

I am building a project using bluetooth control as well as an ir sensor. The logic behind my program is when I press a key I want my robot to execute a series of program and while the program is executing if an obstacle is detected I need the motors to stop and then continue from the same point after the obstacle is removed. I am uploading my code for ref.

    #include <Servo.h>
    #include <AFMotor.h>
    #include <Servo.h>
    int obstaclePin = 12;
    int obstacle = LOW;
    AF_DCMotor motor1(1);
    AF_DCMotor motor2(2);
    AF_DCMotor motor3(3);
    AF_DCMotor motor4(4);
    Servo myservo1;
    Servo myservo2;
    int pos = 0;

    char bt='S';
    void setup()
    {
      Serial.begin(9600);
      pinMode(obstaclePin,INPUT);
      myservo1.attach(10);
      myservo2.attach(9);
      motor1.setSpeed(100);
      motor2.setSpeed(100);
      motor3.setSpeed(100);
      motor4.setSpeed(100);
      Stop();
    }

    void loop() {
     bt=Serial.read();
      if(bt=='F')
    {
      forward();
      delay(2000);
      backward();
      delay(2000);
      left();
      delay(2000);
      right();
      delay(2000);
      Stop();
    }

    if(bt=='B')
    {
    forward();
     delay(8000);
     left();
     delay(1500);
     ServoControl();
     delay(500);
     backward();
     delay(1000);
     right();
     delay(3000);
     forward();
     delay(8000);
     Stop();
    }

    if(bt=='L')
    {
     forward();
     delay(10000);
     left();
     delay(1500);
     ServoControl();
     delay(500);
     backward();
     delay(1000);
     right();
     delay(3000);
     forward();
     delay(10000);
     Stop();
    }

    if(bt=='R')
    {
     forward();
     delay(12000);
     left();
     delay(1500);
     ServoControl();
     delay(500);
     backward();
     delay(1000);
     right();
     delay(3000);
     forward();
     delay(12000);
     Stop();
    }

    if(bt=='S')
    {
     Stop();
    }
    if(bt=='O')
    {
      servoOpen();
    }
    if(bt=='C')
    {
      servoCLose();

    }

    }
    void forward()
    {
      motor1.run(FORWARD);
      motor2.run(FORWARD);
      motor3.run(FORWARD);
      motor4.run(FORWARD);
    }

    void backward()
    {
      motor1.run(BACKWARD);
      motor2.run(BACKWARD);
      motor3.run(BACKWARD);
      motor4.run(BACKWARD);
    }
    void left()
    {
      motor1.run(FORWARD);
      motor2.run(FORWARD);
      motor3.run(RELEASE);
      motor4.run(RELEASE);
    }
    void right()
    {
      motor1.run(RELEASE);
      motor2.run(RELEASE);
      motor3.run(FORWARD);
      motor4.run(FORWARD);
    }
    void Stop()
    {
      motor1.run(RELEASE);
      motor2.run(RELEASE);
      motor3.run(RELEASE);
      motor4.run(RELEASE);
    }
    void servoOpen()
    {
      for (pos = 0; pos <= 100; pos += 1) { // goes from 0 degrees to 180 degrees
        // in steps of 1 degree
        myservo1.write(pos);
        myservo2.write(pos);
      }
    }

    void servoCLose()
    {

      for (pos = 100; pos >= 0; pos -= 1) { // goes from 180 degrees to 0 degrees
        myservo1.write(pos);
        myservo2.write(pos);
      }
    }
    void ServoControl()
    {
      for (pos = 0; pos <= 100; pos += 1) { // goes from 0 degrees to 180 degrees
        // in steps of 1 degree
        myservo1.write(pos);
        myservo2.write(pos);
        delay(40);                       // waits 15ms for the servo to reach the position
      }
      for (pos = 100; pos >= 0; pos -= 1) { // goes from 180 degrees to 0 degrees
        myservo1.write(pos);
        myservo2.write(pos);
        delay(40);                       // waits 15ms for the servo to reach the position
      }
    }
    void obstacleD()
    {
      obstacle = digitalRead(obstaclePin);
       if(obstacle == HIGH)
      {
        Stop();
      }
    }

I don't know where to add the obstacle detection so it would work like an interrupt. the main problem I was experiencing was that whenever I tried running the code on my Arduino it would completely change the logic and noting would work even if I put the command in the serial monitor until an obstacle was detected. I'm a newbie at programming and using Arduino.

body:
Your main problem is, that you are using many blocking calls, especially `delay()`. During that the Arduino cannot do anything else. You need to use a non-blocking coding style, doing multiple things one after another in fast succession. Here the style from the `BlinkWithoutDelay` example using `millis()` is very useful. There are lots of tutorials about that online (on this site or many others), so I will not go into detail, how that works.

---

**Quick fix:** If you just need a quick fix and the code structure of your project is not relevant for your grade, you can do the following:

Replace the `obstacleD()` function with one, that will also wait for a specific time and also check the IR sensor during that time. Something like this:

    void obstacleD(unsigned long wait, void (*function)(void)){
        unsigned long start_time = millis();
        unsigned long already_waited = 0;
        while(millis()-start_time < wait-already_waited){
            if(digitalRead(obstaclePin)){
                already_waited += millis()-start_time;
                Stop();
                while(digitalRead(obstaclePin));
                start_time = millis();
                function();
            }
        }
    }

Then in the rest of your code instead of `delay(1000)` (or similar) you are calling

    obstacleD(1000, forward);

The first parameter is the waiting time, the second one is the function, that was lastly called (since we need to recall it, if an obstacle is found and then removed). We are noting the start time of the function into `start_time`. The first while loop will loop, until we waited as long as provided (difference between current time and start time will then be greater than the wait time minus the time we already waited). In that loop we are checking the IR sensor pin. If it reads HIGH, we add the elapsed time to our `already_waited` variable, stop and then loop while the IR sensor pin stays high. When the pin goes LOW again we leave this inner while loop, update to our new `start_time` and again execute the function to start the motors again. The code should continue the path like without an obstacle, even if multiple time an obstacle is placed during one path element.

Note, that the above code is not tested in any way. You might need to make minor changes.

---

**Interrupt quick fix:** You could implement the stopping on obstacle with an actual interrupt. Something like this:

    void obstacle_detected(){
        while(digitalRead(obstaclePin));
    }

    void setup(){
        ...
        attachInterrupt(obstaclePin, obstacle_detected, RISING);
    }

Though this is also not a good solution, since you totally block any other code, until the obstacle is removed, including receiving serial data (one byte is received by the hardware, but that has to be read by an interrupt. If another byte is send before that, the original byte is lost). Normally you would only set a flag in the ISR (interrupt service routine), but your main code isn't ready for using that flag correctly.

---

**The good-structured-code way:** To get the desired behavior with a good structured code, you need to completely restructure/rewrite your current code. As mentioned above you need to create a code, that does not block for long times, but only does things, if they need to be done at that time, and otherwise execute other code. You need to learn the usage of `millis()`.

Also your code would greatly benefit from a Finite State Machine (FSM), as Majenko already wrote in a comment. Here you first draw a diagram with your complete behavior structure, divided up into states, that do exactly one thing. The states are connected by state transitions (arrows from one state to another) (and we can even repeat a state by drawing an arrow from a state back to itself). Then you can convert that into a code structure using a state variable (integer or enum) and a `switch` statement, where each case has the code for one state. You can look at my answer to [this question][1] for more information. Or you can search for the term "finite state machine" or "FSM" on this site or google (for google you maybe should add "arduino" to the search query to get relevant results).

All in all you would create a code, that handles the wanted behavior without any hardware interrupts (not really needed here) and which is easily extendable, without getting problems with the program flow.

---

Note:

The for loop in `servoCLose()` is totally unnecessary. You don't have any delay to slow it down, so it will go to the end position in way less time, than the motor needs to even start moving. Just use `Servo.write()` one single time there with the desired angle. That is enough, unless you want it to move slowly. Then you would need a way to delay between the writes (either `delay()` or with `millis()`, depending on your then overall approach).

  [1]: https://arduino.stackexchange.com/questions/63488/wanted-to-control-2-servos-with-serial-read/63491#63491


message:
Issue with bluetooth and a large number LED strip

I want to be able to control multiple LED strip via bluetooth with one arduino.
I coded my own android app and everything work fine with one or two led strip with few pixel. But as soon as I had to many pixel data send by BT is missing a few byte (ex "colfff5dff" instead of "color fff5dff"). It doen't happen every time but it's unrealiable.
I feel like sending data to the led strip take so many time that it skip some letter.

I'm ussing dsd tech hc-05 with an arduino UNO R3 and a esp8266 led strip.

```
#include <Adafruit_NeoPixel.h>
#include <SoftwareSerial.h>

#ifdef __AVR__
 #include <avr/power.h>
#endif

//SoftwareSerial blueTooth(13,12);

#define PIN       5
#define SIZE      200

#define BRIGHTNESS 200

enum MODE {FIXED, LOOP_RGB, RUNNING, RAINBOW};
enum MODE mode = FIXED;

Adafruit_NeoPixel strip(SIZE, PIN, NEO_RGB + NEO_KHZ800);

int lastTime;

uint32_t color;
char Incoming_value = 0;
char bufferStr[100];
int bufferIndex = 0;

void setup() {

  Serial.begin(9600); //open the serial port
  Serial.setTimeout(10);
  strip.begin();
  strip.show();
  strip.setBrightness(50);

  color = Adafruit_NeoPixel::Color(0, 255 ,0 );
}

void loop() {
  if(Serial.available() > 0)
  {
    String s = Serial.readString();
    Serial.print(s);

    //I've tried some other way like read();  readString();  readBytes(); readBytesUntil();

    /*
     * ---- not needed for the issue
     */
  }
  switch (mode){
    case FIXED : fixedMode(); break;
    case RUNNING : runningLights(); break;
    case RAINBOW : rainbow(); break;
    }
    showAll();
}

void parseBlueTooth(){
  //---- not needed for the issue
}

void fixedMode(){
  setAll(color);
  showAll();
}

void rainbow(){
  //---- not needed for the issue
}

void runningLights() {
  //---- not needed for the issue
}

void setAll(byte r, byte g, byte b) {
  setAll(Adafruit_NeoPixel::Color(r,g,b));
}

void setAll(uint32_t color) {
  strip.fill(color, 0, SIZE);
}

void showAll(){
  long curTime = millis();
  if(curTime - lastTime >16){
    if(strip.canShow()) {
      strip.show();
    }
    lastTime = curTime;
  }

}
```

body:
Your problem is that you are using two blocking routines that can't operate together. Both the SoftwareSerial and the NeoPixel objects take time to perform operations stopping anything else from happening.

* SoftwareSerial blocks inside an ISR while receiving a byte
* NeoPixel blocks with interrupts disabled while outputting the LED status

That means that while NeoPixel is being updated SoftwareSerial is incapable of receiving any data.  It was fine when you only had a few LEDs, since NeoPixel only took a very short time to update, but now that you have more LEDs it takes too long to update and SoftwareSerial can no longer work reliably.

In order to get around the problem you will have to use a hardware UART port. The Uno only has one - pins 0/1 and the `Serial` object. If you're not using that for communication with your computer you can connect your Bluetooth module there instead and use `Serial` instead of `SoftwareSerial` - however you will most probably need to disconnect your Bluetooth module every time you want to upload fresh code to your Arduino.


body:
IMHO, after reading Majenko and raddevus reply,
you may do something to "reduce missing data"

1. reduce baud rate (may be 9600), give more time for bluetooth data transfer.

2. add a checksum byte for your data.

Rererence :

https://lucidar.me/en/serialib/most-used-baud-rates-table/


message:
LCD randomly goes one character further in the ascii table

Here's my code:
```
#include <LiquidCrystal.h>
int rs = 11;
int rw = 10;
int en = 9;
int d0 = 1;
int d1 = 2;
int d2 = 3;
int d3 = 4;
int d4 = 5;
int d5 = 6;
int d6 = 7;
int d7 = 8;
LiquidCrystal lcd(rs, rw, en, d0, d1, d2, d3, d4, d5, d6, d7);

void setup() {
  // put your setup code here, to run once:
  lcd.begin(16, 2);
  Serial.begin(4800);
  lcd.setCursor(0,0);
  lcd.print("Loading...");
  delay(3000);
  lcd.setCursor(1,1);
  lcd.print("waht");
}

void loop() {

}
```
And here's the output:
[![enter image description here][1]][1]

  [1]: https://i.stack.imgur.com/CupPK.jpg

Also note the first line of text starts in the second column. I've tried with a different LCD and the same issue occurs. It seems to go one character further in ascii (ex: the '**.**'s become '**/**') if that's any clue to what's going on. In a separate program (exact same setup) I can print "Hello World" on the first line no problem. Anyone know why it's doing this and how to fix it? Thanks

body:
Your Least Significant Bit is always 1 (Check the [ASCII table][1] to see this).
You might have a problem with your wiring, double check the pin you use and that the continuity is good.

Also, as [KIIV][2] said in comment, depending on the board you use, you might have a conflict with the serial port (Which pull the line high when not transmitting, explaining the result you get). Try moving pin 1 to another one.

  [1]: https://en.wikipedia.org/wiki/ASCII
  [2]: https://arduino.stackexchange.com/users/23841/kiiv


message:
How do i make this map() application work as intended?

I want to map the value range 0-63 like this:
```
x       y
0-15  = 0
16-31 = 1
32-47 = 2
48-63 = 3
```

However, using map function `y = map(x, 0, 63, 0, 3);` returns:

```
x       y
0-15  = 0
16-31 = 0
32-47 = 1
48-63 = 2
```

Is this due to truncating fractions, or something else?

Is there a better alternative?

body:
`map()` doesn't *quite* work as you'd expect.  The formula is:
```
(x - in_min) * (out_max - out_min) / (in_max - in_min) + out_min
```

And all those values are `long`, which is a "long" integer. So all operations are done as integers, and that means that you lose an awful lot of precision in the calculation, since all decimal components are completely ignored.

It means that you only get the maximum output when you put in the maximum input.

As Michael Keijzers notes your expected output is `x/16` (or `x>>4` in bitwise notation), and that can be achieved with `map()` if you set the maximum input to be 48, not 63.

However a simple right shift 4 bits (or divide by 16 if the compiler is clever enough to implement it as a right shift) is a more efficient solution by far, since the processing involved is almost negligible, whereas multiplying and dividing is a relatively expensive set of operations.


body:
You could try:

```c++
y = map(x, 0, 64, 0, 4);
```

Majenko showed you the formula used by `map()`. You can check that the
formula works nicely if you think in terms of half-open intervals:

[0, 64) → [0, 4)

But this is still way less efficient than a bit shift.


message:
Regulate Water Pumps flow by DC Stepper Motor Driver

I'm an Arduino beginner. I've got 2 x 12V DC water pumps

https://www.ebay.co.uk/itm/224461221015

plus 12V, 2A AC/DC adapter to feed them.

I would like to regulate the speed (flow) of the pumps programmatically by Arduino. My first idea was to use 2 channel Relay, however, it only supports two states - on/off. Then I discovered this DC Stepper Motor Driver:

https://www.ebay.co.uk/itm/274521887403

That seems to be a good fit in terms of specifications, but I'm not sure whether it will work with the pumps? It makes me think of whether the DC Stepper Motor Driver may work with only specific motors?

Thanks for any advice!

body:
Yes, it will work.

You can control the speed of the water pumps with a PWM signal by using:

    analogWrite(PWM_pin, value)

Or you can use a cheap transistor like a P2N2222A; here is a [full tutorial][1].

  [1]: https://www.instructables.com/How-to-drive-a-DC-Motor-with-Transistor-Arduino-Tu/


body: Unfortunately after trying it does not work as expected. It has been mentioned that it must be a **BRUSHED** motor and most of these pumps on eBay are **Brushless**.


message:
Nature of the voltage reference instability of internal 1.1V reference of ATmega328P (Nano)

The [ATmega328P data sheet][1] in table 29-11 on page 324 notes that the internal 1.1V reference (VBG) may vary between 1.0V and 1.2V. In [this answer][2] this is called "not stable or accurate".

Question: Is this "unstable" or "inaccurate" or even both if I define it as

   * "unstable" if it varies over the day, say with temperature or VCC or or some such.
   * "inaccurate" if it is a rather stable voltage for a specific Nano-board I have in hand, just not the typical 1.1V.

In the latter case I could measure the value accurately and scale my analog measurements with the measured value instead of the 1.1V.

  [1]: https://ww1.microchip.com/downloads/en/DeviceDoc/ATmega48A-PA-88A-PA-168A-PA-328-P-DS-DS40002061B.pdf
  [2]: https://arduino.stackexchange.com/a/19914/60620

body:
I would say it was "stable but not accurate". The internal reference uses a [bandgap voltage reference](https://en.wikipedia.org/wiki/Bandgap_voltage_reference), which is pretty stable over the operating temperature range of the IC.

The output of the bandgap reference *is* fed through an amplifier to buffer it, which may introduce some instability with temperature, but this is not documented so cannot even be estimated.

The inaccuracy comes from minor differences in the manufacturing process. These don't change over time, so once calibrated for a precise value of voltage reference you should not see much in the way of variance in that value for different temperatures or power supply fluctuations.


message:
Convert float to byte, from Arduino to Raspberry Pi i2c

I'm trying to send the temperature value from the DHT sensor to a raspberry pi through I2C.
Which is the best way to do it?. The temp value is a float, and I think I have to convert it to byte and send that with Wire.write() to the raspberry, is that right?.
Right now I'm sending bytes from the raspberry (with Python) to the Arduino (C++):
Python:

    from smbus import SMBus
    import time

    address = 0x8
    bus = SMBus(1)

    While True:
      bus.write_byte(address, 4)
      time.sleep(1)
      print(bus.ready_byte(address))

Arduino code:

    #include <Wire.h>
    #include <DHT.h>
    ...

    void setup() {
      dht.begin();
      Wire.begin(0x8);
      Wire.onReceive(receiveEvent);
    }

    void receiveEvent () {
      float temp = dht1.readTemperature();
      delay(1000);
      byte tempByte[4] = {temp, 0, 0, 0};
      Wire.write(tempByte[0]);
    }

So the raspberry is printing 0.

Thanks for any help.

body:
First of all, if you want the Arduino to send data as a slave, it should
do so `onRequest()`, not `onReceive()`. Thus:

```c++
void setup() {
    Wire.begin(0x08);
    Wire.onRequest(handleRequest);
}
```

Next, as pointed out by chrisl in a comment, you should not delay within
the `onRequest` handler. I would go further and say that you should not
even call `dht1.readTemperature()`, as that could take too much time to
be done in interrupt context. Instead, have the main loop query the
sensor periodically, and have the latest reading always available:

```c++
volatile float temperature;  // latest valid reading

void loop() {
    float new_temperature = dht1.readTemperature();
    noInterrupts();
    temperature = new_temperature;
    interrupts();
    // ...
}
```

Note that the latest value is updated with interrupts disabled. This is
to avoid a data race that could happen if the Arduino receives a request
while it is in the middle of updating the value. Notice also that
interrupts are disabled during a very short time: just the time needed
to update the variable.

Lastly, to send the data, you can use the version of `Wire.write()` that
accepts a buffer of arbitrary length:

```c++
void handleRequest() {
    Wire.write((uint8_t *) &temperature, sizeof temperature);
}
```

The temperature will be sent LSB-first, as a float, formatted as per
IEEE 754. The Raspberry Pi should be able to digest it in this very same
format.


message:
Need HELP!! Serial communication has a very "Strange Problem"

I am working on building a serial command receiver. The idea is came from the boot loader. However, I got a very strange problem that I have no idea what could cause it.

As the first screenshot show, the print isn't finished because "===a=" is stuck, like this.
[![enter image description here][1]][1]

 In the code, it should print out and the others.

    char* receiveCmd(Stream &_serial, char &cmd_ptr, int &l_ptr) {
      Stream* serial = &_serial;

      if (serial->available() && (uint8_t)serialRead(_serial) == CMD_START) {
        int buf_count = 0; //start at data
        cmd_ptr = serialRead(_serial); //cmd_byte

        char low_byte = serialRead(_serial);
        char high_byte = serialRead(_serial);

        uint16_t length = low_byte; //data_length
        length = length | (high_byte << 8);

        Serial.println("\n\n===a===");
        Serial.println(length);
        Serial.println("===b===");

        l_ptr = (int)length;

        char* _buf = (char*)malloc(length * sizeof(char));

        while (buf_count != length) {
          if (serial->available()) {
            _buf[buf_count] = serial->read();
            buf_count++;
          }
        }

        char checksum = serialRead(_serial); //checksum, don't bother it yett
        char stop_byte = serialRead(_serial);

        if (stop_byte != CMD_EOF) {
          free(_buf);
          return NULL; //error
        }

        return _buf;
      }

      return NULL;
    }

Anyway, the problem is fixed when I print out other variables first, then the length var..

    char* receiveCmd(Stream &_serial, char &cmd_ptr, int &l_ptr) {
      Stream* serial = &_serial;

      if (serial->available() && (uint8_t)serialRead(_serial) == CMD_START) {
        int buf_count = 0; //start at data
        cmd_ptr = serialRead(_serial); //cmd_byte

        char low_byte = serialRead(_serial);
        char high_byte = serialRead(_serial);

        uint16_t length = low_byte; //data_length
        length = length | (high_byte << 8);

        Serial.println("\n\n===a===");
        Serial.println(low_byte, HEX);
        Serial.println(high_byte, HEX);
        Serial.println(length);
        Serial.println("===b===");

        l_ptr = (int)length;

        char* _buf = (char*)malloc(length * sizeof(char));

        while (buf_count != length) {
          if (serial->available()) {
            _buf[buf_count] = serial->read();
            buf_count++;
          }
        }

        char checksum = serialRead(_serial); //checksum, don't bother it yett
        char stop_byte = serialRead(_serial);

        if (stop_byte != CMD_EOF) {
          free(_buf);
          return NULL; //error
        }

        return _buf;
      }

      return NULL;
    }

Other code is exactly the same. Does anyone know what may cause it? I can't print out those thing during production because it is only for debugging. If I remove those print, the code is also stuck(because of the length variable again).

For additional information, the serial signal is generated from other Arduino and AltSerial Library. The structure is like this.

    void sendCmd(Stream &_serial, char cmd, char* payload, int length) {
      Stream* serial = &_serial;
      char buf[6 + length]; //start, data_length, data, checksum, stop

      buf[0] = CMD_START; //start_byte
      buf[1] = cmd; //cmd_byte
      buf[2] = length & 0xff; //data_length - low byte
      buf[3] = (length >> 8) & 0xff; //data_length - high byte
      buf[4 + length] = (char)calcCRC(payload); //checksum
      buf[5 + length] = CMD_EOF; //stop_byte

      for (int i = 0; i < length; i++) //load buf
        buf[4 + i] = payload[i];

      for (int i = 0; i < sizeof(buf); i++)
        serial->print(buf[i]);
    }

 I have used `Serial.print(altSerial.read(), HEX)` to check whether the byte is received correctly. They are all correct. That's why it is confusing me.QAQ

===== UPDATED INFORMATION =====

I have narrowed the problem. It seems like the below code is the main cause regard the issue. But no solution for this still.

    uint16_t length = low_byte; //data_length
    length = length | (high_byte << 8);

Thank you.

  [1]: https://i.stack.imgur.com/SSrLJ.png

body:
Why it does not work? You already got the answer in comments:

- You are reading more bytes from the serial stream than what you know
  are available. Then, your `length` variable can contain garbage, which
  makes `malloc()` fail even if you have plenty of available memory.

- You write into the memory buffer even if the allocation failed, which
  makes your program corrupt its memory. From this point, anything can
  happen.

You may notice that the behavior of your program depends on the timing.
Adding more instructions, or delays, may make it work. This is simply
because you give your peer more time to send its data packet. Of course,
relying on the timings is not a good approach: you instead have to make
sure you never `read()` more than what is actually `available()`.

Here is an (untested) attempt to do this correctly and in a non-blocking
fashion. It is based on a [finite state machine][fsm]. What is original
about this state machine is that it is implemented as a `switch`/`case`
where _every single case_ falls through:

```c++
/*
 * Packet format:
 *   CMD_START cmd_byte length_L length_H [payload] checksum CMD_EOF
 */
char *receiveCmd(Stream &serial, char &cmd_ref, int &l_ref) {

    // The current state is defined by what parts of the packet
    // we have already received.
    static enum {
        GOT_NONE, GOT_START, GOT_HEADER, GOT_PAYLOAD
    } state = GOT_NONE;

    // Variables only valid in the states GOT_HEADER and GOT_PAYLOAD.
    static char cmd_byte;
    static uint16_t length;
    static char *buffer;
    static size_t buffer_pos;

    switch (state) {
        case GOT_NONE:
            if (serial.available() < 1 || serial.read() != CMD_START)
                break;
            state = GOT_START;
            // fallthrough
        case GOT_START:
            if (serial.available() < 3)
                break;
            cmd_byte = serial.read();
            length = serial.read();
            length |= (uint16_t) serial.read() << 8;
            buffer = (char *) malloc(length);
            if (!buffer) {
                Serial.print(F("ERROR: Failed to allocate "));
                Serial.print(length);
                Serial.println(F(" bytes."));
                state = GOT_NONE;
                break;
            }
            buffer_pos = 0;
            state = GOT_HEADER;
            // fallthrough
        case GOT_HEADER:
            while (buffer_pos < length && serial.available())
                buffer[buffer_pos++] = serial.read();
            if (buffer_pos < length)
                break;
            state = GOT_PAYLOAD;
            // fallthrough
        case GOT_PAYLOAD:
            if (serial.available() < 2)
                break;
            serial.read();  // consume checksum
            if (serial.read() != CMD_EOF) {
                Serial.println(F("ERROR: Expected CMD_EOF."));
                free(buffer);
                state = GOT_NONE;
                break;
            }
            cmd_ref = cmd_byte;
            l_ref = length;
            state = GOT_NONE;
            return buffer;
    }
    return NULL;
}
```

You can think of this `switch`/`case` as a set of actions to perform
sequentially in order to process the whole packet. However, if the
function gets stuck for lack of incoming data, it just bails out. On the
next call, the `switch` puts it back where it left.

[fsm]: https://majenko.co.uk/blog/finite-state-machine


message:
Adafruit Thermal Printer unwanted gradient

I have thermal printer from adafruit and when printing images I have problems getting a proper black.

I tried playing with the dot print time and the dot feed time using the `setTimes` function, but this seem to have no effect.

```cpp
  unsigned long dotPrintTime = 3000*30L;
  unsigned long dotFeedTime = 2100*30L;
  printer.setTimes(dotPrintTime, dotFeedTime);
```

Also the `setHeatConfig` seems to have no effect. I tried different values.

```cpp
  uint8_t dots = 11;
  uint8_t _time = 120;
  uint8_t interval = 40;
  printer.setHeatConfig(dots, _time, interval);
```
Here an image of the result:

[![enter image description here][1]][1]

  [1]: https://i.stack.imgur.com/iffIS.jpg

Is it possible to print fully black the whole width of the paper?

body:
Thermal printers generate quick pulses of heat to change thermal paper from white to a darker color.  This may require more than the expected amount of current most Arduino project need.

Consider checking the maximum current rating of your power source.  From the [Adafruit printer web page][1] regarding using [this Mini Thermal Receipt Printer][2]:

> This printer in particular requires 5 to 9 Volts, 1.5 Amps current!
> That means you will need a fairly beefy supply and you cannot run it
> off of USB power. An external adapter is required!

Also consider trying different thermal paper manufactures and colors.

Lastly, consider how you might avoid [BPA from thermal paper][3].

  [1]: https://learn.adafruit.com/mini-thermal-receipt-printer/power
  [2]: https://www.adafruit.com/product/597
  [3]: https://www.sciencedaily.com/releases/2014/10/141022143628.htm


message:
How can I add an additional temperature sensor (EZO RTD of Atlas Scientific) to an Atlas Scientific bare-bones wifi pool kit?

## Problem summary

When I changed the I2C address of a sensor (EZO RTD) to another address (e.g., 50 or 100) from its default address (102), it didn't work on my Atlas Scientific bare-bones WiFi Hydroponics Kit.

## Specific description

I tried to add a temperature sensor (EZO RTD) to an Atlas Scientific bare-bones WiFi Hydroponics Kit that already has a pH Sensor (EZO pH) and a temperature sensor (EZO RTD) on the pH port and Temperature port, respectively. Since a provided setup guide of Atlas Scientific says that each sensor on the kit has to have a different I2C address when multiple sensors are used on it. So I assigned an I2C address "50" to the additional sensor and then added it to the AUX port (and tried the Temperature port as well), but it didn't work at all. Meanwhile, the temperature sensor with the default I2C address 102) works very well on both the Temperature and AUX ports. I guess this might be related to a coding problem. Atlas Scientific's provided code is as follows: THE CODE IS DELETED BY MYSELF

Thanks for reading my problem.

Jayjay

@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@

I solved this problem based on the answer I voted for.

The code I made is as follows:

```
#include <iot_cmd.h>
#include <ESP8266WiFi.h>                                         //include esp8266 wifi library
#include "ThingSpeak.h"                                          //include thingspeak library
#include <sequencer4.h>                                          //imports a 4 function sequencer
#include <sequencer1.h>                                          //imports a 1 function sequencer
#include <Ezo_i2c_util.h>                                        //brings in common print statements
#include <Ezo_i2c.h> //include the EZO I2C library from https://github.com/Atlas-Scientific/Ezo_I2c_lib
#include <Wire.h>    //include arduinos i2c library

WiFiClient client;                                              //declare that this device connects to a Wi-Fi network,create a connection to a specified internet IP address

//----------------Fill in your Wi-Fi / ThingSpeak Credentials-------
const String ssid = "WIFI NAME";                                 //The name of the Wi-Fi network you are connecting to
const String pass = "WIFI PASSWORD";                             //Your WiFi network password
const long myChannelNumber = ;                            //Your Thingspeak channel number
const char * myWriteAPIKey = "";                 //Your ThingSpeak Write API Key
//------------------------------------------------------------------

Ezo_board PH = Ezo_board(99, "PH");       //create a PH circuit object, who's address is 99 and name is "PH"
Ezo_board EC = Ezo_board(100, "EC");      //create an EC circuit object who's address is 100 and name is "EC"
Ezo_board RTD = Ezo_board(102, "RTD");    //create an RTD circuit object who's address is 102 and name is "RTD"
Ezo_board RTD2 = Ezo_board(50, "RTD2");   //create an RTD circuit object who's address is 50 and name is "RTD2"
Ezo_board PMP = Ezo_board(103, "PMP");    //create an PMP circuit object who's address is 103 and name is "PMP"

Ezo_board device_list[] = {   //an array of boards used for sending commands to all or specific boards
  PH,
  EC,
  RTD,
  RTD2,
  PMP
};

Ezo_board* default_board = &device_list[0]; //used to store the board were talking to

//gets the length of the array automatically so we dont have to change the number every time we add new boards
const uint8_t device_list_len = sizeof(device_list) / sizeof(device_list[0]);

//enable pins for each circuit
const int EN_PH = 14;
const int EN_EC = 12;
const int EN_RTD = 15;
const int EN_AUX = 13;

const unsigned long reading_delay = 1000;                 //how long we wait to receive a response, in milliseconds
const unsigned long thingspeak_delay = 15000;             //how long we wait to send values to thingspeak, in milliseconds

unsigned int poll_delay = 2000 - reading_delay * 2 - 300; //how long to wait between polls after accounting for the times it takes to send readings

//parameters for setting the pump output
#define PUMP_BOARD        PMP       //the pump that will do the output (if theres more than one)
#define PUMP_DOSE         -0.5      //the dose that the pump will dispense in  milliliters
#define EZO_BOARD         EC        //the circuit that will be the target of comparison
#define IS_GREATER_THAN   true      //true means the circuit's reading has to be greater than the comparison value, false mean it has to be less than
#define COMPARISON_VALUE  1000      //the threshold above or below which the pump is activated

float k_val = 0;                                          //holds the k value for determining what to print in the help menu

bool polling  = true;                                     //variable to determine whether or not were polling the circuits
bool send_to_thingspeak = true;                           //variable to determine whether or not were sending data to thingspeak

bool wifi_isconnected(){                            //function to check if wifi is connected
  return (WiFi.status() == WL_CONNECTED);
}

void reconnect_wifi(){                                    //function to reconnect wifi if its not connected
  if(!wifi_isconnected()){
    WiFi.begin(ssid, pass);
    Serial.println("connecting to wifi");
  }
}

void thingspeak_send(){
  if (send_to_thingspeak == true) {                                                    //if we're datalogging
    if(wifi_isconnected()){
      int return_code = ThingSpeak.writeFields(myChannelNumber, myWriteAPIKey);
      if (return_code == 200) {                                                          //code for successful transmission
          Serial.println("sent to thingspeak");
      }else{
        Serial.println("couldnt send to thingspeak");
      }
    }
  }
}

void step1();      //forward declarations of functions to use them in the sequencer before defining them
void step2();
void step3();
void step4();
Sequencer4 Seq(&step1, reading_delay,   //calls the steps in sequence with time in between them
               &step2, 300,
               &step3, reading_delay,
               &step4, poll_delay);

Sequencer1 Wifi_Seq(&reconnect_wifi, 10000);  //calls the wifi reconnect function every 10 seconds

Sequencer1 Thingspeak_seq(&thingspeak_send, thingspeak_delay); //sends data to thingspeak with the time determined by thingspeak delay

void setup() {

  pinMode(EN_PH, OUTPUT);                                                         //set enable pins as outputs
  pinMode(EN_EC, OUTPUT);
  pinMode(EN_RTD, OUTPUT);
  pinMode(EN_AUX, OUTPUT);
  digitalWrite(EN_PH, LOW);                                                       //set enable pins to enable the circuits
  digitalWrite(EN_EC, LOW);
  digitalWrite(EN_RTD, HIGH);
  digitalWrite(EN_AUX, LOW);

  Wire.begin();                           //start the I2C
  Serial.begin(9600);                     //start the serial communication to the computer

  WiFi.mode(WIFI_STA);                    //set ESP8266 mode as a station to be connected to wifi network
  ThingSpeak.begin(client);               //enable ThingSpeak connection
  Wifi_Seq.reset();                       //initialize the sequencers
  Seq.reset();
  Thingspeak_seq.reset();
}

void loop() {
 String cmd;                            //variable to hold commands we send to the kit

  Wifi_Seq.run();                        //run the sequncer to do the polling

  if (receive_command(cmd)) {            //if we sent the kit a command it gets put into the cmd variable
    polling = false;                     //we stop polling
    send_to_thingspeak = false;          //and sending data to thingspeak
    if(!process_coms(cmd)){              //then we evaluate the cmd for kit specific commands
      process_command(cmd, device_list, device_list_len, default_board);    //then if its not kit specific, pass the cmd to the IOT command processing function
    }
  }

  if (polling == true) {                 //if polling is turned on, run the sequencer
    Seq.run();
    Thingspeak_seq.run();
  }
}

//function that controls the pumps activation and output
void pump_function(Ezo_board &pump, Ezo_board &sensor, float value, float dose, bool greater_than){
 if (sensor.get_error() == Ezo_board::SUCCESS) {                    //make sure we have a valid reading before we make any decisions
    bool comparison = false;                                        //variable for holding the reuslt of the comparison
    if(greater_than){                                               //we do different comparisons depending on what the user wants
      comparison = (sensor.get_last_received_reading() >= value);   //compare the reading of the circuit to the comparison value to determine whether we actiavte the pump
    }else{
      comparison = (sensor.get_last_received_reading() <= value);
    }
    if (comparison) {                                               //if the result of the comparison means we should activate the pump
      pump.send_cmd_with_num("d,", dose);                           //dispense the dose
      delay(100);                                                   //wait a few milliseconds before getting pump results
      Serial.print(pump.get_name());                                //get pump data to tell the user if the command was received successfully
      Serial.print(" ");
      char response[20];
      if(pump.receive_cmd(response, 20) == Ezo_board::SUCCESS){
        Serial.print("pump dispensed ");
      }else{
        Serial.print("pump error ");
      }
      Serial.println(response);
    }else {
      pump.send_cmd("x");                                          //if we're not supposed to dispense, stop the pump
    }
  }
}

void step1() {
  //send a read command. we use this command instead of RTD.send_cmd("R");
  //to let the library know to parse the reading
  RTD.send_read_cmd();
  RTD2.send_read_cmd();
}

void step2() {
  receive_and_print_reading(RTD);             //get the reading from the RTD circuit
    if ((RTD.get_error() == Ezo_board::SUCCESS) && (RTD.get_last_received_reading() > -1000.0)) { //if the temperature reading has been received and it is valid
    PH.send_cmd_with_num("T,", RTD.get_last_received_reading());
    EC.send_cmd_with_num("T,", RTD.get_last_received_reading());
    ThingSpeak.setField(2, String(RTD.get_last_received_reading(), 2));                 //assign temperature readings to the third column of thingspeak channel
  } else {                                                                                //if the temperature reading is invalid
    PH.send_cmd_with_num("T,", 25.0);
    EC.send_cmd_with_num("T,", 25.0);                                                          //send default temp = 25 deg C to EC sensor
    ThingSpeak.setField(2, String(25.0, 2));                 //assign temperature readings to the third column of thingspeak channel
  }

  Serial.print(" ");
  receive_and_print_reading(RTD2);
  if ((RTD2.get_error() == Ezo_board::SUCCESS) && (RTD2.get_last_received_reading() > -1000.0)) { //if the temperature reading has been received and it is valid
    PH.send_cmd_with_num("T,", RTD2.get_last_received_reading());
    EC.send_cmd_with_num("T,", RTD2.get_last_received_reading());
    ThingSpeak.setField(3, String(RTD2.get_last_received_reading(), 2));                 //assign temperature readings to the third column of thingspeak channel
  } else {                                                                                //if the temperature reading is invalid
    PH.send_cmd_with_num("T,", 25.0);
    EC.send_cmd_with_num("T,", 25.0);                                                          //send default temp = 25 deg C to EC sensor
    ThingSpeak.setField(3, String(25.0, 2));                 //assign temperature readings to the third column of thingspeak channel
  }

}

void step3() {
  //send a read command. we use this command instead of PH.send_cmd("R");
  //to let the library know to parse the reading
  PH.send_read_cmd();
  EC.send_read_cmd();
}

void step4() {
  receive_and_print_reading(PH);             //get the reading from the PH circuit
  if (PH.get_error() == Ezo_board::SUCCESS) {                                          //if the PH reading was successful (back in step 1)
     ThingSpeak.setField(1, String(PH.get_last_received_reading(), 2));                 //assign PH readings to the first column of thingspeak channel
  }
  Serial.print("  ");
  receive_and_print_reading(EC);             //get the reading from the EC circuit
  if (EC.get_error() == Ezo_board::SUCCESS) {                                          //if the EC reading was successful (back in step 1)
     ThingSpeak.setField(2, String(EC.get_last_received_reading(), 0));                 //assign EC readings to the second column of thingspeak channel
  }

  Serial.println();
  pump_function(PUMP_BOARD, EZO_BOARD, COMPARISON_VALUE, PUMP_DOSE, IS_GREATER_THAN);
}

void start_datalogging() {
  polling = true;                                                 //set poll to true to start the polling loop
  send_to_thingspeak = true;
  Thingspeak_seq.reset();
}

bool process_coms(const String &string_buffer) {      //function to process commands that manipulate global variables and are specifc to certain kits
  if (string_buffer == "HELP") {
    print_help();
    return true;
  }
  else if (string_buffer.startsWith("DATALOG")) {
     start_datalogging();
    return true;
  }
  else if (string_buffer.startsWith("POLL")) {
    polling = true;
    Seq.reset();

    int16_t index = string_buffer.indexOf(',');                    //check if were passing a polling delay parameter
    if (index != -1) {                                              //if there is a polling delay
      float new_delay = string_buffer.substring(index + 1).toFloat(); //turn it into a float

      float mintime = reading_delay*2 + 300;
      if (new_delay >= (mintime/1000.0)) {                                       //make sure its greater than our minimum time
        Seq.set_step4_time((new_delay * 1000.0) - mintime);          //convert to milliseconds and remove the reading delay from our wait
      } else {
        Serial.println("delay too short");                          //print an error if the polling time isnt valid
      }
    }
    return true;
  }
  return false;                         //return false if the command is not in the list, so we can scan the other list or pass it to the circuit
}

void get_ec_k_value(){                                    //function to query the value of the ec circuit
  char rx_buf[10];                                        //buffer to hold the string we receive from the circuit
  EC.send_cmd("k,?");                                     //query the k value
  delay(300);
  if(EC.receive_cmd(rx_buf, 10) == Ezo_board::SUCCESS){   //if the reading is successful
    k_val = String(rx_buf).substring(3).toFloat();        //parse the reading into a float
  }
}

void print_help() {
  get_ec_k_value();
  Serial.println(F("Atlas Scientific I2C hydroponics kit                                       "));
  Serial.println(F("Commands:                                                                  "));
  Serial.println(F("datalog      Takes readings of all sensors every 15 sec send to thingspeak "));
  Serial.println(F("             Entering any commands stops datalog mode.                     "));
  Serial.println(F("poll         Takes readings continuously of all sensors                    "));
  Serial.println(F("                                                                           "));
  Serial.println(F("ph:cal,mid,7     calibrate to pH 7                                         "));
  Serial.println(F("ph:cal,low,4     calibrate to pH 4                                         "));
  Serial.println(F("ph:cal,high,10   calibrate to pH 10                                        "));
  Serial.println(F("ph:cal,clear     clear calibration                                         "));
  Serial.println(F("                                                                           "));
  Serial.println(F("ec:cal,dry           calibrate a dry EC probe                              "));
  Serial.println(F("ec:k,[n]             used to switch K values, standard probes values are 0.1, 1, and 10 "));
  Serial.println(F("ec:cal,clear         clear calibration                                     "));

  if(k_val > 9){
     Serial.println(F("For K10 probes, these are the recommended calibration values:            "));
     Serial.println(F("  ec:cal,low,12880     calibrate EC probe to 12,880us                    "));
     Serial.println(F("  ec:cal,high,150000   calibrate EC probe to 150,000us                   "));
  }
  else if(k_val > .9){
     Serial.println(F("For K1 probes, these are the recommended calibration values:             "));
     Serial.println(F("  ec:cal,low,12880     calibrate EC probe to 12,880us                    "));
     Serial.println(F("  ec:cal,high,80000    calibrate EC probe to 80,000us                    "));
  }
  else if(k_val > .09){
     Serial.println(F("For K0.1 probes, these are the recommended calibration values:           "));
     Serial.println(F("  ec:cal,low,84        calibrate EC probe to 84us                        "));
     Serial.println(F("  ec:cal,high,1413     calibrate EC probe to 1413us                      "));
  }

  Serial.println(F("                                                                           "));
  Serial.println(F("rtd:cal,t            calibrate the temp probe to any temp value            "));
  Serial.println(F("                     t= the temperature you have chosen                    "));
  Serial.println(F("rtd:cal,clear        clear calibration                                     "));
 }
```

body:
Did you update the code above to add your new sensor?

A quick look at Atlas' site and their Github page didn't find an obvious instruction to do what you're try to do, so that's the first thing I'd try if you haven't already. Below the Thinkspeak Credentials section, add your new device to the I2C devices definitions, then add its name to the array of available devices. I called the new temp sensor RTD2 in my example below, but you could probably call it something more descriptive of its function or placement. It looks like there is a name string in each definition that (I'm guessing) will be displayed in Thingspeak's data, and would be a good place to put a short description.

```c++
        Ezo_board PH = Ezo_board(99, "PH");       //create a PH circuit object, who's address is 99 and name is "PH"
        Ezo_board EC = Ezo_board(100, "EC");      //create an EC circuit object who's address is 100 and name is "EC"
        Ezo_board RTD = Ezo_board(102, "RTD");    //create an RTD circuit object who's address is 102 and name is "RTD";
        Ezo_board RTD2 = Ezo_board(50, "RTD2");   //create an RTD circuit object who's address is 50 and name is "RTD2"
        Ezo_board PMP = Ezo_board(103, "PMP");    //create an PMP circuit object who's address is 103 and name is "PMP"

        Ezo_board device_list[] = {   //an array of boards used for sending commands to all or specific boards
          PH,
          EC,
          RTD,
          RTD2,
          PMP
        };
```

Update:

On review, it looks like you'll need to define an Arduino pin to enable the new device (in the `//enable pins for each circuit` section) and enable it at the head of `setup()` where the the other devices' pins are set to OUTPUT mode, and set this pin HIGH (guessing that your new RTD will be identical to your current one):

```c++
//enable pins for each circuit
const int EN_PH = 14;
const int EN_EC = 12;
const int EN_RTD = 15;
const int EN_RTD2 =    <some available pin# here> ;
const int EN_AUX = 13;
```

And in setup():

```c++

 pinMode(EN_RTD2, OUTPUT);

  ...

 digitalWrite(EN_RTD2, HIGH);
```

Update 2:

I think what we did above will get your new sensor data logged to Thingspeak, since I see a message referring to a "datalog mode" in `print_help()`. If you're expecting the control process to act your new sensor data in some way, you'll need to understand what it does now and what you want it to do differently based on the newly available data. But I would still take getting the system to just log the new data as your first step.


message:
Custom assert() implementation: not printing the error message

I am writing my own assert() macro on Arduino as shown below.
When I run it **from the main() it always works correctly** (prints the message and gets into an infinite loop), however when I call it within a class function it gets stuck without printing anything. Why is that?

assert.cpp/.h
```
#ifndef _ASSERT_H_
#define _ASSERT_H_

void assertion_failure(const char* expr, const char* file, int linenum);

#define assert(expr) \
    if (expr) ; \
    else assertion_failure(#expr, __FILE__, __LINE__)

#endif /* _ASSERT_H_ */
```
```
#include "assert.h"
#include "Arduino.h"

void assertion_failure(const char* expr, const char* file, int linenum)
{
    Serial.print("Assertion failed in '");
    Serial.print(file);
    Serial.print("' on line ");
    Serial.print(linenum);
    Serial.print(": ");
    Serial.println(expr);
    Serial.flush();

    while (1);
}
```

And the context in which the assert gets stuck below (it works well when I call it in main() however):
```
int ADS1256::assert_debug()
{
    uint8_t id = read_register(STATUS) >> 4;
    assert(false);    // Gets stuck here without printing anything to screen
    return id;
}
```

---

EDIT:
looks like it has something to do with build configuration. I am using PlatformIO build system.
It does not work when I use this file structure:
```
├── include
│   └── assert.h
├── lib
│   ├── ADS1256
│      ├── ads1256.cpp
│      ├── ads1256.h
│      └── ads1256_regmap.h
├── src
    ├── assert.cpp
    └── main.cpp
```

However, if I move assert.cpp/.h into a dedicated directory within lib/ it works fine. What is the reason behind this?
How can I investigate why this happened?

It works with this layout (again, using PlatformIO default build configuration):
```
├── include
├── lib
│   ├── ADS1256/
│   ├── Assert/
│       ├── assert.cpp
│       └── assert.h
├── src
    └── main.cpp
```

body:
As per comment on question, this is not as finished as I'd like, but it's a start.

I deeply suspect what you're running into is a conflict between the name of your header and the standard `assert.h` header.  You're using the same header name and same macro names as is used in the standard c header, that is part of both c++ and "Arduino.".  The standard `assert()` with the way things are normally set up on the AVR Arduino core does basically just go into a tight loop and do nothing.

I would consider naming your macro something other than `assert` and naming your header something other than `assert.h`.  If you want to get into the precise details why, we need to see things like your include path order, and the include directives themselves.  Even then, the advice would be about the same.

Diagnostics
-----------

#### `--save-temps`

In platform.io you should be able to add `--save-temps` to the `avr-gcc` command-line to get it to produce (or keep) the output of the preprocessing stage.  GCC annotates these showing where each section of the entire output came from, so you can see which headers each `#include` directive actually included and in what order all of this happened.

#### NDEBUG

Something else you can try, as a diagnostic measure, is to define `NDEBUG` in your project settings. This is usually defined by IDEs for "release mode".  It basically makes `assert()` into a NOP, which in turn means that it will not do the usual avr-libc thing of locking up.  If you're seeing the avr-libc assert being expanded instead of your own, then the behaviour will change to just not locking up, but also not doing what your own `assert` would do.

AVR-based Arduino `assert()` support
------------------------------

avr-libc's `assert()` tries to print its assertion message on stderr, which is not configured on AVR based Arduinos to do anything.  So the outward behaviour is that it locks up.  However, you can complete [avr-libc's implementation][1] of stderr in terms of the Arduino's `Serial.write` function, in which case the normal avr-libc `assert` will work just fine.  Here's [one example][2] of completing avr-libc's stdio printing in terms of `Serial`.

`__FILE__` Caveat and SRAM
------------------------

Something you should be aware of in using `__FILE__`, and therefore `assert` (whether it be avr-libc's or yours) is that `__FILE__` expands to a string literal which is the full path of the source filename, which can be quite long.  On the UNO (you have tagged) these go into SRAM.  So if you use `assert` in a couple different files, you can very quickly eat up the available SRAM on the AVR.

For this reason, in my own little assert-type macros, I've taken to not reporting the file but instead a custom tag, which is often just a single letter or number.  Besides, often my asserts are blinking the `__LINE__` number on an LED, where `__FILE__` is impractical in my typical use case anyway.

  [1]: https://www.nongnu.org/avr-libc/user-manual/group__avr__stdio.html
  [2]: https://github.com/maniacbug/RF24/blob/master/examples/pingpair/printf.h


message:
Run computation only on request over serial

An Arduino Nano is set up to perform A/D conversions and send results out over `Serial`. Currently the code structure is like

    loop() {
      delayUntilNextTargetTime();
      measure();
      sendMeasurementsToSerial();
    }

Though I make already sure that `delayUntilNextTargetTime` does not blindly `delay(MILLIS)` but rather subtracts the computation time from the time to sleep to prevent drift, I would rather get the timing from the host computer.

The idea is that the host computer sends a command string over the serial when it wants data, so the loop could look like

    loop() {
      if (!Serial.available()) return;
      measure();
      sendMeasurementsToSerial();
    }

Now I wonder if there is a way to do this without idle polling, something along the lines of

    loop() {
      if(Serial.available()) {
        measure();
        sendMeasurementsToSerial();
      }
      sleepUntilSerialPotentiallyHasData();
    }

I read that saving power is hard and likely not worth the effort, in particular when having a USB power supply. It is pure curiosity to see

 - what it takes to bring the system into, say, IDLE mode, possibly stopping the timers too, because they are not used (I guess)
 - and what it takes to get out of IDLE mode correctly again such that A/D conversion in `measure()` works without flaws.

body:
On a Nano you can `#include <avr/sleep.h>`, then simply call
`sleep_mode()` from `loop()`. This will put the device to sleep, by
default in IDLE mode, until the next interrupt fires. The Nano will wake
up at least once every 1,024 µs, to service the timer interrupt
that is used to implement the Arduino timing function(`millis()`,
`delay()`, etc.). Most of the time this `loop()` will do nothing more
than testing `Serial.available()`, so the MCU will be awake only for a
couple of microseconds every 1,024 µs, which is not much.

If you disable the timer interrupt, all the timing functions will be
off, but the MCU will still be waken by the serial port interrupt as
soon as data is available.


message:
What does avrdude: Device signature = 0x000000 mean? Faulty wiring? Software issue? Incorrect tutorial?

I followed this [tutorial][1] a couple of times and when I clicked on bootloader I get this error:
```
avrdude: Device signature = 0x000000
```

To see the configuration file click [here][2].

 1. Why do I get this error (Arduino can't communicate with chip, problem with software)?
 2. How can I fix it?
 3. Is something in the tutorial incorrect?

>Keep in mind I use an `Arduino Uno Rev. 3` and `ATmega328P`

  [1]: https://www.electronicshub.org/burn-bootloader-on-atmega328/
  [2]: https://drive.google.com/open?id=1AZmnBH_1yHPGG1DSEl8AVRWUc3kWIbN4

body:
There is one part of the tutorial that is incorrect - or rather *missing*.

When you open the serial port the Arduino resets. That includes when the serial port is opened by `avrdude`.

You need to prevent that from happening, so that the ArduinoISP sketch receives the serial data, not the Arduino's bootloader.

There's a number of ways of doing that:

* Add a 10uF or greater capacitor between RESET and GND on the Arduino
* Add a small (say 100R) resistor between RESET and 5V on the Arduino
* Cut the RESET-EN trace on the underside of the Arduino

Of those my preferred method is the first: add a 10uF or greater capacitor between RESET and GND on the Arduino.

----

**Update:**

Now that you have provided photographs of your actual setup I can see that the ground wire between your Arduino and the breadboard is actually plugged into the VIN pin of the Arduino, not GND.


body:
Unfortunately the three prominent threads on the Arduino forum on this topic are closed, so their good but incomplete information is baked in time:

 - [Invalid device signature error](https://forum.arduino.cc/t/invalid-device-signature-error/962328/2)
   - Which references: [Did I get these ArduinoISP instructions right?](https://forum.arduino.cc/t/did-i-get-these-arduinoisp-instructions-right/308935)
 - [Invalid Device signature = 0x000000](https://forum.arduino.cc/t/invalid-device-signature-0x000000/922497)
 - [no clock on Atmega328p-AU](https://forum.arduino.cc/t/no-clock-on-atmega328p-au/225563/4)

So let me add a bit more useful information in the hope it permeates.

> Device signature = 0x000000

Means the MCU **did not respond with a signature**. There is a very thin chance that's because it reported all zeros when asked for a signature, but a much higher chance that **it did not respond at all**. Correct signature bytes are found [here](https://onlinedocs.microchip.com/pr/GUID-CBDC1838-0100-4F26-A45A-134958193C3B-en-US-4/index.html) (eg. ATmega328P = 0x1E950F) and crucially, all Atmel microcontrollers have one.

Further, the error:

> avrdude: Device signature = 0x000000
>
> avrdude: Yikes! Invalid device signature.

will occur if you're using ArduinoISP to flash a target Arduino and the **target is not physically connected**. So it really is an "all bets are off" message that doesn't pinpoint any particular cause. To troubleshoot, checking wiring if a good first step.

Do not, on the other hand, concern yourself with the external clock signal. In contrast to some guides, the ATmega328P at least comes factory configured to use an internal RC oscillator, so even a correctly connected crystal or resonator on the `XTAL` pins will not show any activity until the first successful flash.


body:
Can confirm previous answer about changing SPI clock.
I edited ArduinoISP.ino example and changed `#define SPI_CLOCK (1000000 / 6)` to `#define SPI_CLOCK (128000/6)` and after that I successfully burned bootloader to my UNO


message:
How can I read the Timer direction in phase correct PWM?

I have had to use Timer0 with phase correct PWM and a prescaler of 1. This results in a 32khz PWM frequency and obviously impacts millis, delay and micros. (Timer1 and Timer 2 are also in use so changing to those is not an option)

millis() is trivial to work around - multiply by 32 as the TOV0 interrupt handler is called 32 times more frequently (subject to overflow of course)

micros() is somewhat trickier - as normally it is the Timer0 overflow count (as used in millis() though shifted in this case) plus the current value of TCNT0. That works great when TCNT0 is increasing only and resetting to 0 after MAX - but in phase correct PWM it could be going upwards or downwards.

I think what I need to do is find the direction the Timer is currently using - but pouring over the datasheet for the ATmega328P I can't seem to find a way to do so...

Is there a way of reading this, eg from a register I can interrogate for it?

Alternatively can anyone else think of a way to get microsecond (or close - 10 microsecond would be good enough) resolution when all timers are in phase correct mode?

I'm considering a fall-back of reading TCNT0 twice and deriving it from that - with a prescaler of 1I am assuming it is not possible to read it twice faster than it could change - however I'd prefer a neater solution if there is one.

body:
I decided to go with the inspect method and modified wiring.c accordingly - may not fit everyone's use case but solves mine (along with a couple of tweaks changing the #define's to volatile variables and adding a setter for them.

micros updated to:

    unsigned long micros() {
      unsigned long m;
      uint8_t oldSREG = SREG, t1, t2;

      cli();
      m = timer0_overflow_count;
    #if defined(TCNT0)
      t1 = TCNT0;
      t2 = TCNT0;
    #elif defined(TCNT0L)
      t1 = TCNT0L;
      t2 = TCNT0L;
    #else
      #error TIMER 0 not defined
    #endif

    #ifdef TIFR0
      if ((TIFR0 & _BV(TOV0)) && (t1 == timer0_phase_correct ? 0 : 255))
        m++;
    #else
      if ((TIFR & _BV(TOV0)) && (t1 == timer0_phase_correct ? 0 : 255))
        m++;
    #endif

      SREG = oldSREG;

      if (timer0_phase_correct && t1 > t2){
        t2 = 510 - t2;
      }

      return (m * us_per_timer0_overflow) + (clockCyclesToMicroseconds(timer0_prescale * t2));
    }


message:
Is there anything wrong with this code

Hi I'm pretty new to cpp.
Could someone review my code and explain any pitfalls or problems?
Below is the code and an example to read from a flow meter with a hall sensor.
Thanks in advance.
Greg

```c++
    /** example
    #include "flow.h"
    Flow f(3);
    Flow f2(4);
    volatile unsigned int counter;
    void flow_counter() // ISR
    {
          // Increment the pulse counter
          counter ++;
    }

    void setup()
    {
      f.start(); //using default ISR
      f2.assign_isr(&flow_counter);
      f2.assign_counter(&counter);
      f2.start();
    }

    void loop()
    {
     Serial.printf("flow rate on 3 = %f \n",f.rate());
     Serial.printf("flow total = %dml %f%% of 500ml \n",f.total_ml(),f.percent(500));
     Serial.printf("flow rate on 4 = %f \n",f2.rate());
     delay(1000);
    }

    */

    #include <math.h>
    #include "Arduino.h"

    volatile unsigned int flowPulseCounter;
    void flowCounter() // ISR
    {
          // Increment the pulse counter
          flowPulseCounter ++;
    }

    class Flow{
      public:
        Flow(uint8_t pin)
        {
          if(flowPin==254)
           flowPin = pin;
        }

        void assign_isr ( void (*isr)()){ this->flowISR = isr; };
        void assign_counter (volatile unsigned int * counter ){ this->counter = counter; };
        void assign_pin(uint8_t pin){ flowPin = pin; };

        void  set_calibration_factor( float factor ) { this->calibrationFactor = factor; };
        float get_calibration_factor( ) { return this->calibrationFactor; };

        uint8_t retrieve_pin(){ return flowPin; };

        void start()
        {
          detachInterrupt(digitalPinToInterrupt(this->flowPin));
          *this->counter = 0; // counter is a pointer so * assigns the value at that address to 0
          this->flowRate = 0;
          this->flowMillilitres = 0;
          this->flowMilliseconds = millis();
          pinMode(this->flowPin, INPUT_PULLUP);
          this->running = true;
          attachInterrupt(digitalPinToInterrupt(this->flowPin), this->flowISR, FALLING);
        }

        void calculate()
        {
          if(this->running)
          {
            this->flowRate = ((1000.0 / (millis() - this->flowMilliseconds)) * ( *this->counter )) / this->calibrationFactor;
            this->flowMilliseconds = millis();
            // convert to millilitres.
            this->flowMillilitres = (this->flowRate / 60) * 1000;
            // Add the millilitres to the cumulative total
            this->totalMillilitres += this->flowMillilitres;
          }
        }

        void stop()
        {
          detachInterrupt(digitalPinToInterrupt(flowPin));
          this->calculate();
          this->running = false;
          pinMode(this->flowPin, INPUT_PULLUP);
        }

        bool is_max( uint32_t millilitres )
        {
          this->calculate();
          return (this->totalMillilitres >= millilitres) ? true : false;
        }

        float percent( uint32_t millilitres )
        {
          this->calculate();
          return (float)((double) this->totalMillilitres / (double) millilitres)  * 100.0;
        }

        float rate ()
        {
          this->calculate();
          return this->flowRate;
        }

        uint32_t total_ml()
        {
          this->calculate();
          return this->totalMillilitres;
        }

      private:
        uint8_t flowPin=0;
        uint32_t flowMilliseconds = 0;
        float flowRate=0;
        uint32_t flowMillilitres = 0;
        uint32_t totalMillilitres = 0;
        float calibrationFactor = 4.5;
        bool running = false;
        void (*flowISR)() = &flowCounter;
        volatile unsigned int * counter = &flowPulseCounter;
    };

```

body:
It's hard to answer without any description of the actual problem.

On the top of my head, with that much code i'd consider starting off by creating a separate class declaration, and write your member definitions outside. It will make the code way more manageable, and easier to troubleshoot.

https://www.learncpp.com/cpp-tutorial/class-code-and-header-files/

Also, you have several include statements in at least two different places. They usually go first in a file, along with include guards. If your code consists of separate files, please make that clear to readers.