text:
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

You wrote:

TIMSK5 |= OCIE5A;

You mean
TIMSK5 |= _BV(OCIE5A);

or, equivalently,
TIMSK5 |= 1 << OCIE5A;

Hmm, not sure I understand.  The 'TIMSK5 |= OCIE5A' line comes directly from my currently-working code as the last line of the TIMER5 interrupt setup block, so I'm pretty sure it's correct.  The 'TIMSK5 = 0' line will reliably stop the ISR from firing, so I'm pretty sure it is correct as well.

Do you mean that the 'TIMSK5 |= _BV(OCIE5A);' should be used to re-enable the ISR, instead of 'TIMSK5 |= OCIE5A'

@user3765883, OCIE5A is just #define OCIE5A  1.  That is, it is the index or place number of the bit within TIMSK5 and not the mask value that you need for use with |=.

Aw, rats!  I mis-read the TIMERx setup code.  What I thought was 'TMSK5 |= OCIE5A;' was actually 'TMSK5 |= (1 << OCIE5A);' which (I think) is the equivalent of 'TIMSK5 |= _BV(OCIE5A);'  Sorry for wasting your time :(


text:
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!");
  }
}

It's called "integer wraparound" - int can only hold between -32768 and +32767 on an 8-bit Arduino.

Omg, thank you very much for the help. I was struggling with it

tip, if you know that it only should contain positive numbers, declare as an unsigned integer.

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.

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.

source: Stack Exchange

license: Creative Commons - Attribution Share-Alike - https://creativecommons.org/licenses/by-sa/4.0/

sort: votes


text:
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++;
//  }

Tried changing if with while at while (pos < DATA_SIZE && current_time >= scen1[pos].time). But no change

The else if can just be an else. I'd start by making sure if if statement is being entered, then sanity-checking the two temperatures in the comparison. might also be beneficial to set up a test rig that compresses time and fakes the sensor data.

Thank you @DaveNewton. Yes, changed the else if using just else but seems to work likewise. Also, compressing time (in my case I set up an interval of 1 minute and 2 minutes), the relay doesn't' t change with simulated temp data.

So I think dumping out temperature1 and scen1[pos].temperature would be a good idea to sanity-check all assumptions. There's nothing obvious jumping out at me at the moment. (Changing from else if to else wasn't a fix, just a simplification.) I'd normalize all time values to unsigned long (you're currently mixing long and unsigned long comparisons, but the high bit isn't set, so shouldn't matter.

I've managed discarding the if (pos < DATA_SIZE && current_time >= scen1[pos].time) and using just if and if else/else. I kept both temperature1 and scen1[pos].temperature and the loop is working ok.
So, I could identify where is the issue. Obviously I have to see now how to add a statement/loop for time

I'm not sure what you just said, but if you're comparing hard-coded times against an actual time, you might be better off having only time offsets in scen1.time and adding a known "real"-time offset so they're in the future. It's not super-clear to me what you're trying to do here, but if you're trying to test something then I wouldn't be using anything "real" other than a simple on-board time difference check.

Thanks, @DaveNewton. Sorry I wasn't' t clear. Just updated the post with the previous info, so it is now easier to show how I tested and what is the current issue.

So the time comparison is likely failing (or it's blowing through the loop really fast if the time is always >=). Hence dumpling out the comparison values to check assumptions.

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.

So it's blowing through the loop, which still means the time comparison is failing. Hence the repeated suggestion to check your assumptions by looking at the times. There's zero way we can help you without knowing what the data values are that are being compared, and you won't share them. This isn't an answer to the problem, it's a work-around that breaks the program.

Thanks. Yes, I checked the times. I compared the current_time and the scen1[pos].time. Simplified the code and checked if current_time is equal or bigger of scen1[pos].time. The output is right (using different times and intervals). So I would expect the statement working fine. I don' t know the checking of assumptions means something else of that I've already done.

My point was that we cannot check your assumptions or provide any meaningful input without knowing what's actually happening. Comparisons generally Just Work, so if removing pos++ "fixes" it (ergo pos < DATA_SIZE forever) it means there's an issue in the time comparison. But we cannot see the any of the values being compared, so all we can do is guess.

I see and agree. Have updated the reply with the solution (this one really reproducing what I want).

all_licenses: Creative Commons - Attribution Share-Alike - https://creativecommons.org/licenses/by-sa/4.0/


text:
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 module by connecting the VIN pin to my battery and VOUT to my arduino ?

https://hackaday.io/project/25461-reading-the-max471-sensor-module, also https://github.com/wisewolf/Arduino-Power-Meter.

what kind of a 9 V battery?

If you only need to measure voltage, why not use an Arduino A/D input?  All you need to do is connect a voltage divide across the 9V terminals to divide down to the A/D range.  Use big resistors in the 100K to 1Meg range for low drain.

@Boggyman: If there are other analogRead channels active, 100k to 1M might be a bit high to load the ADC in time. An additional capacitor in parallel to the voltage divider low side might help...

@jsotola This is a 9V GF22

@Boggyman when you talk about ADC you refer to this module : ADS1015 ?

No, I'm referring to the analog inputs that are already included on the Arduino, that you can read with analogRead

@Boggyman Do you think this setup is correct? R1 = 9kΩ, R2 = 1KΩ https://ibb.co/BqGZCBS

That would work, but it's not optimal.  It would divide the 9 V battery down to 1 V, which is wasting 4/5 of the 5 V A/D range.  Also, the total resistance is only 10 K, which is a continuous drain on the battery.  I'd suggest something like R1 = R2 = 100 K to give 4.5 V and drain less current.  Depending on your overall application, you may be able to use 1 Meg as long as you are not using multiple A/D channels as @DataFiddler mentioned.

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).

Are you sure that this would allow me to power my Arduino, if so is there a difference in autonomy with this module rather than the assembly of @Boggyman (less wasting) ?


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

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

You already have done, haven't you?

Or do you mean a schematic? That can be done by various tools, for example Eagle ir KiCAD (though that is only a small part of their functionality)

I mean schematic

Do you want to create a schematic that contains the contents of the other modules? Then you need to get the schematics of those modules and copy them, then join them up with lines, just as you have here.

If you don't need the contents of the modules, then the schematic pretty much boils down to a block diagram.  You can do this with Windows Paint, or whatever drawing program you are familiar with... no need for any specialized schematic software with a big learning curve.  Just draw trial sketches with pencil and paper, then when you have the layout you like, create the same in Paint.  Tip: Create a separate Paint image with any symbols you want to use, like upward-pointing power arrow, ground symbol, wire cross. Keep that open and copy/paste into your final drawing.

It is often the case in professionally done schematics to "block" sub assemblies.  For instance your phone likely contains a GPS receiver and in some cases this is OEM'ed from a different manufacture who doesn't provide a schematic of the insides. Also, schematic capture programs are used to generate PCBs, 3D Board Models and BOMs.  MSPaint can't do that.

See Rules and guidelines for drawing good schematics 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.

simulate this circuit – Schematic created using CircuitLab
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.


text:
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:
// 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!

in Arduino you can use macro ARDUINO_{build.board}  where build.board is defined in boards.txt for example as uno.build.board=AVR_UNO. the #idef is then #ifdef ARDUINO_AVR_UNO

the more you can avoid board detection, the more places your program will run or just need a slight modification instead of something that confuses the developer.

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.

I'm most interested in the pico, which would be RP2040 or some variant of that name. I'm not sure it uses the GCC compiler, could be wrong though.

Almost everything that's not Microsoft uses the GCC compiler...


text:
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.

You need to learn about Finite State Machines. delay() is your enemy.

"Work like an interrupt" can mean two different things: one is that obstacle detection (OD) can be an actual interrupt, the other is that instead of blocking with delay we can use other timing mechanisms. The problem with delay is that if OD is an actual interrupt after the ISR runs you'll drop right back into delay, which when you're running into a wall, not cool. That's why the comment regarding FSMs and looking in to other ways to "do something for awhile" w/o using delay.

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 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).

(I'd pedantically point out that delay doesn't disable interrupts, the issue being that once the ISR is done it just goes back to delaying :)

@DaveNewton Though the proposed interrupt solution involves staying in the interrupt, until the obstacle was removed. That might be very long, thus not that good. I mentioned the point of maybe not graded code structure.


text:
USB and LM7805 both to power Arduino
I have high current usage For my circuit as you can see below (link):

I like to power Arduino when it is not connected to PC by USB Connection, So I want to add one external power supply and connect it's GND And 5V to Arduino GND And 5V pins.
So with this new circuit, I have two power supply for Arduino uno as you can see below: :
1-USB Connection to PC
2- Powering the Arduino by External Power Supply and LM7805

So I Asked here about connecting two power supply for Arduino (external power supply and PC USB Connection) and check this circuit Safeness for USB Port of PC or the Arduino.
Thanks.

I'm not exactly sure what you're asking.

I don't see a problem with that. Should work

All you have done there is replicate the voltage regulator that is already on the Arduino itself. Seems a bit pointless to me. If you want higher current 5V then you should consider either a 5V supply (USB charger) or a switching regulator instead of linear. Otherwise you're really not achieving anything useful.

@Dave_Newton, I have updated the Question and make it clearer. Also based of the comments, i guess the Circuit would working.

Thanks, @Majenko. the question is When i have USB connection and the second power supply, can I connect GND And 5V pins of the new power supply and the Arduino pins ( GND and 5V Pins) to each others?

Sure you can. Just like the internal regulator is.


text:
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;
  }

}

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

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

add a checksum byte for your data.

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

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.

That's exactly what I did and it got better but not perfect.

Maybe you need to upgrade your Arduino to one that will update the NeoPixels using DMA instead of locking up the CPU.

I'm gonna try that, thanks for the information

I am working with HC-05 also and retrieving files over it.
I send commands and get files back over Bluetooth.  The speed of bluetooth should be fine.  (Although you need to set it faster -- mine's at 38400)
Up in your setup() loop do:
Serial.begin(38400)

Also your code to read off serial is a bit different.
You just need the following:
while (Serial.available()){
    command = Serial.read();
}

I was sending String-based commands but just today I decided to change them to 1 byte commands because it is much easier to deal with in a switch statement.  In the code above my command variable is a byte.
Then my switch looks like the following in loop():
switch (command){
    case 49: { // ASCII Char 1 - get Temperature
      SW_Serial.print(getString(currentRoom) + " : " + currentTemp);
      // CALL YOUR SPECIFIC CODE TO DO EACH THING IN EACH CASE
      break;
    }
    case 50: { // ASCII char 2 - start data write
      // #### Allow Data Write start/stop to be done via BT
      // turns on logging of temp data (to SD card)
      // turn on data writing and LED
      // CALL YOUR SPECIFIC CODE TO DO EACH THING IN EACH CASE
...

Of course, each time through the loop you should set your command variable back to 0 (I use 0 as the no-command).  Otherwise you'll keep processing on the same command value.


text:
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:

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

Looks like it gets one or two least significant bits wrong. So check wiring and so

Btw, Arduino pins 0 and 1 are wired to USB serial (on many boards) - so you can try it without Serial.begin and if it works, just move pin(s) to not use arduino pin 1

Your Least Significant Bit is always 1 (Check the ASCII table 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 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.


text:
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?

you can use y = x  / 16

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.

Re “if the compiler is clever enough to implement it as a right shift”: it will do so only if the divided is unsigned, or if it can convince itself that it can never be negative.

You could try:
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.


text:
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!

Even though they call that a "stepper motor driver" it's nothing more than a basic H-bridge that can drive any brushed DC motors (two per driver).

I would add that the L298N is a relatively inefficient driver--I might aim for a different driver, like a 6612 etc.

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.

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.


text:
Nature of the voltage reference instability of internal 1.1V reference of ATmega328P (Nano)
The ATmega328P data sheet 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 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.

I would say it was "stable but not accurate". The internal reference uses a 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.


text:
Receiving code between atmega328P (C) and Feather m0 (Arduino)
I've tried to create a receiver code for receiving my data (really only want the ac/gy values and nothing else) and use the following main code for sending via C programming: https://github.com/YifanJiangPolyU/MPU6050/blob/master/main.c
the sending receiving code in Arduino this far is the following (that doesn't work):
void do_send(osjob_t* j){
    // Check if there is not a current TX/RX job running
    if (LMIC.opmode & OP_TXRXPEND) {
        Serial.println(F("OP_TXRXPEND, not sending"));
    } else {
        // Prepare upstream data transmission at the next possible time.

byte strArray[30];
    int i = 0;
    if(Serial1.available()>0) {
       while (Serial1.available()>0){
          strArray[i] = Serial1.read();
          i++;
       }
            // send the 6 bytes payload to LoRaWAN port 7 --> now port 1
            LMIC_setTxData2(1, strArray, sizeof(strArray), 1); //might need to be converted to type data, not char.

            digitalWrite(LED_BUILTIN, HIGH);    // turn the LED on by making the voltage HIGH                      //optional: for confirmation
    }
        }
    }
    // Next TX is scheduled after TX_COMPLETE event.
    //delay(60000);

I've noticed that I cannot send char arrays with LMIC function for the feather m0, so I tried receiving it as a byte array which works to send. Any help/suggestions/snippets of code etc. would be greatly appreciated.

https://majenko.co.uk/blog/reading-serial-arduino


text:
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.

Please remove the delay from the onReceive callback function. It is executed inside an ISR. Delay doesn't work there

First of all, if you want the Arduino to send data as a slave, it should
do so onRequest(), not onReceive(). Thus:
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:
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:
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.

Thank you very much Edgar!!!.
I'm trying now to read the IEEE 754 value from the Raspberry Pi, using Python3, but no success so far. I'm new to these technologies so sorry for my ignorance. With Python 3 I'm reading this from the bus with:
float bus.read_byte_data(address, 4)  # this returns an array like: ["205","104"] when the temperature value is 25.20  float bus.read_byte(address)  # this returns random numbers of 3 digits, like 204, 104, etc.
Not sure if Python3 is the right choice here, maybe you could recommend something else better. Thanks again.

I don't know Python, and it's off-topic here. If you forcibly set temperature to 25, you should read the bytes 0x00, 0x00, 0xc8 and 0x41, in this order. How you reassemble these on the PC is a question for another site.


text:
ESP32 Espressif ESP32_DevKitC_V4 in platformio: flash issues
I am using the Espressif ESP32_DevKitC_V4 with platformio, and i cannot flash the board. I read about the various "button dance" procedures, and the ES32-WROVER and the ESP32-WROVER-B seem to behave differently as well.
From the 80 tries of doing the "button dance" i got it one time to work. Are there any other options on how to flash the board with platformio without attaching a 100nF capacitor from EN to GND?
Here is the output when trying to flash
Auto-detected: /dev/ttyUSB0
Uploading .pio/build/ESP32/firmware.bin
esptool.py v3.0
Serial port /dev/ttyUSB0
Connecting........_
Chip is ESP32-D0WD (revision 1)
Features: WiFi, BT, Dual Core, 240MHz, VRef calibration in efuse, Coding Scheme None
Crystal is 40MHz
MAC: 4c:11:ae:6c:c8:b4
Uploading stub...

A fatal error occurred: Invalid head of packet (0x65)
*** [upload] Error 2  ==========

[FAILED] Took 9.83 seconds ==========================
    The terminal process "platformio 'run', '--target', 'upload'" terminated with exit code: 1.

These are the settings in the platformio.ini file:
[env:ESP32]
platform = espressif32
framework = espidf
board = esp32dev
board_build.flash_mode = dio

Thanks everyone for the help!

Reduce the programming baud rate?

A genius solved this problem by attaching a 100nF capacitor from EN to GND.


text:
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.

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.

please, no pictures of text ... add the actual text

@jsotola Do you mean the code? Ok, I will change it.

Are you sure _buf is actually being allocated? You should always check if malloc() returns NULL before using the memory you think you've allocated.

@Majenko Thank you so much! It seems like the cause of the problem, but how do I check the buffer has been allocated?

if (_buf == NULL) { // do something to alert the user and abort the operation }

@Majenko It is not allocated because of the lack of memory?  I think that I have enough memory for that.

It's always worth checking. You may think you have enough, but you may not, since other things besides you use the memory.

Also, what is the function serialRead()?

@Majenko
char serialRead(Stream &_serial) {
Stream* serial = &_serial;
delay(1);
return (uint8_t)serial->read();
}

And what baud rate are you working at?

You should only ever read from serial if .available() has told you that there is actually a byte there to read, or if you check that you actually read a byte after reading (it will return -1 if there was nothing to read). You check if there is at least one byte available, then proceed to read loads of bytes that may, or may not, be there. You're entirely beholden to timing quirks to get it right, and that is bad. You should always wait for a byte to actually be there before attempting to read it.

Here is an example of how to handle reading of packets in a non-blocking manner.

@Majenko I did, there is a loop function to repeatedly check there is any available byte to read. Only after that, function receiveCmd will be called. The baud rate is 115200.

Yes, but you only check once for a single byte at the start of readCommand, and then proceed to read multiple bytes. How do you know those bytes have arrived? You don't.

https://majenko.co.uk/blog/reading-serial-arduino

what for is the pointer alias Stream* serial if you have a reference?

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. What is original
about this state machine is that it is implemented as a switch/case
where every single case falls through:
/*
 * 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.

Thank you very much. I have found the problem. It is just not enough memory. therefore, it fails. However, I will take your suggestion for the 'receiveCmd' function.


text:
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.
  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.
  uint8_t dots = 11;
  uint8_t _time = 120;
  uint8_t interval = 40;
  printer.setHeatConfig(dots, _time, interval);

Here an image of the result:

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

Does the test page you get from holding the button print correctly? How are you powering it?

I already recognized that the barcode also gets light grey, printing the full width. The adapter I am using is 2.4A and 5.0V.

Just to be clear, the barcode you're talking about is the QR code from the test page?

no it is not...

Alright, I don't know what you're saying, or why, or to whom.  The reason why I'm asking about the test page (as seen here) that you get from holding the power button is because the test page happens entirely under the printer's control, and not your code.  Which means if you have the problem with the test page, your code and the Adafruit library are irrelevant to fixing the problem.  And that seems like something anyone trying to help would want to know.

It may not actually be a "power" button.  But the button in any case.  The printer also has an escape sequence for printing the page.  So, in theory it could be done that was as well, but it would be better to use the button if possible so that it's certain to be operating under default settings.

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 regarding using this Mini Thermal Receipt Printer:

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.

I was kind of hoping to get them to confirm it before posting an answer, but alright.

Ah, I see ... get them to reason it out for them selves - clever of you.  Hanging out here and other embedded processor stack exchange sites, I've see more than an expected number of problems associated with power supplies not capable of supply the necessary current.  I've been caught on this once or twice my self.

We are all here to improve these questions and answers for people who stumble upon these entries in the future.  I am not sure why there is a down vote but upon reading my answer I see there is no explanation why checking the power supply is a good idea.  So I added one.  If that was not the reason for the vote please leave a comment saying what is missing from the answer.

I can't speak for downvote motivations, but it strikes me as more of a comment/suggestion/request-for-details than answer. It may end up being the/an answer, but currently (see what I did there) it's a guess/hint that may or may not be relevant. I don't know the Arduino SE culture; no idea how it's similar/different to SO, so I don't participate much in voting yet unless I think it's obvious ¯_(ツ)_/¯

I was the initial upvote, in case that needs clarification.

Thanks @timemage.


text:
Having preblem in developing smart curtain
I am developing smart curtain system with voice control using Arduino Uno and bluetooth sensor
Almost of codes is already written. but I have to fix error with delay function.
I am using timer0_millis for time control.
But the one thing I want to fix is that because of delay in timer1 function,
I cannot change the value of a. but it need to be changed when voice is coming.
can anybody help me to fix this?
extern volatile unsigned long timer0_millis;

#include <SoftwareSerial.h>
#include <Stepper.h>
#include <dht.h>
#include <SimpleTimer.h>

SoftwareSerial BT(2, 3);
const int stepsPerRevolution = 64;
Stepper myStepper(stepsPerRevolution, 11, 9, 10, 8);
dht DHT;

#define DHT11_PIN A1

SimpleTimer timer;
char a = BT.read();

void setup() {
    Serial.begin(9600); // Sets the data rate in bits per second (baud) for serial data transmission
    pinMode(7, OUTPUT);
    myStepper.setSpeed(300);
    BT.begin(9600); // Sets digital pin 13 as output pin
}

void loop() {
    if (BT.available()) {
        char a = BT.read();
        if (a == '1') {
            digitalWrite(7, HIGH);
            myStepper.step(2048);
            delay(500);
            Serial.print('1');
        }
        if (a == '2') {
            automode();
        }
        if (a == '3') {
            digitalWrite(7, LOW);
            myStepper.step(-2048);
            Serial.print('2');
            delay(500);
        } if (a == '4') {
            digitalWrite(7, LOW);
            myStepper.step(-2048);
            Serial.print('2');
            delay(500);
        }
    }
}

void automode() {
    int chk = DHT.read11(DHT11_PIN);
    int AnalogValue;
    AnalogValue = analogRead(A0);
    if (DHT.temperature > 30 && AnalogValue > 600) {
        myStepper.step(-2048);
        timer1();
    } else if (DHT.temperature > 30 && AnalogValue < 600) {
        myStepper.step(2048);
        timer1();
    } else if (DHT.temperature < 30 && AnalogValue > 600) {
        myStepper.step(2048);
        timer1();
    } else if (DHT.temperature < 30 && AnalogValue < 600) {
        myStepper.step(-2048);
        timer1();
    }
    return;
}

void timer1() {
    timer0_millis;
    if (timer0_millis >= 100000) {
        timer0_millis = 0;
    }
    do {
        delay(5);
    } while (timer0_millis < 100000);
    return;
}

Sorry, your code doesn't make much sense to me. You include SimpleTimer, but you are not using it. You declare timer0_millis from extern as volatile, but you are using it just as a simple variable and not inside an ISR. And you use delay() and timer0_millis together.

Do not use timer0_millis directly: it's an undocumented implementation detail, and you have a data race every time you access it. Use millis() instead. See Blink without delay.


text:
ShieldBuddy TC275 as a drop-in replacement for MEGA 2560?
I have an autonomous wall-following robot based on a Mega2560, that is just about maxed out in terms of memory usage and speed.  I'm starting to have weird intermittent failures with previously working code; a function will work fine in isolation (same hardware, but only the minimum required code to run just that one function), but not when used with the full program running, and other issues.
I ran across this article about the ShieldBuddy TC275, which purports to be pin-compatible with the Due (which I believe is pin-compatible with the Mega 2560, but I can't use the Due due to 5V compatibility issues), and MUCH faster, even if only Core0 is used.
I realize it is quite costly relative to other Arduino projects, but that's not a factor here.  Anyone have experience with this board as a replacement for a Mega2560?
TIA,
Frank

If it was mostly-working on a 2560 this would be overkill (but entertaining overkill). Level-shifters eliminate 3.3/5V issues, though, or split processing between multiple boards, like using an Arm-based board for computational chores and one or more 5V Arduinos for IO. But the ShieldBuddy's base-level support looks solid--only question would be regarding third-party library support. I'll know more in a week ;)

Ah, would you keep us posted on your progress then?  I spent some time on the ShieldBuddy forum, and there appear to be some problems with 'free entry tool chain' licenses expiring. (https://aurduino.boards.net/thread/251/free-entry-chain-license-expired)

Oooo no; ok, I'll keep an eye out and see what can be figured out.


text:
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                                     "));
 }

Define "changed the I2C address"--the sensor board itself needs to have its I2C address changed--how exactly did you change its I2C address?

@DaveNewton Thanks for your question. I used an Arduino UNO and issued a command, "I2C, 50" in Arduino IDE.

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.
        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):
//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():

 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.

Thanks for your answer. I found a way to solve this problem following part of your answer. I edited my code only based on the first paragraph of your answer but not the rest of it. Rather, I edited void. step1 and void step 2.


text:
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

Is your source named “Assert.c” or “Assert.cpp”? Are you really writing main() rather than setup() and loop()? If so, do you call init() at the start of main()?

I tried the code you posted, with a minimal stub for the ADS1256 class: it works as expected. Your problem thus lies in some part of your code that you are not showing.

Where is assert_debug() being called from?

@EdgarBonet It is named assert.cpp (my mistake when writing the post, sorry). I am indeed calling main() rather than setup+loop.

In that process did you change your #include directive?

@timemage no, I am always using the same: #include "assert.h".
I am guessing that it is somehow clashing with the assert() macro defined in the avr-gcc toolchain somewhere. But how can I verify/prove this?

That's basically what I'm in the process of writing. It's unfinished, but I guess I'll just post it.  I can try to update.

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 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 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.

Thanks for pointing me to avr-libc's implementation of sterr/assert!
So we agree on clashing with the standard assert.h header. But I want to understand what and how the problem arises. Is it the file name, is it macro name, both?
How could I check which implementation was used (e.g. inspecting binary, symbols or sth)?
I tried using -H preprocessor flag (shows absolute paths of included headers), but couldn't see anything useful from it...

Uhh, I will try to make an update to address that.

See under Diagnostics and --save-temps. I'm not (left that out prior) going to be able to go much further with this as an answer really without working out exactly what to ask you to do or include in the question and then having you provide that, which would probably add a lot of noise to the question.

I asked the same question in the PlatformIO community and clashing with avr-libc's assert macro is indeed the problem.

If that's really the answer you're looking for then you might as well post your own answer calling that one out and I'll get rid of this one.  You would need to mark yours as accepted.


text:
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.

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.