text:
Why are raw data bytes not converting to ASCII, but only in one part of my program?
I am writing a program to read from the Atlas Scientific EZO-HUM, -O2, and -CO2 sensors simultaneously via the I2C protocol with an Arduino Uno. The sensors all work, but for some reason, just the O2 sensor data does not convert to ASCII text. Below is my program:
#include <Ezo_i2c.h>
#include <Ezo_i2c_util.h>
#include <iot_cmd.h>
#include <sequencer1.h>
#include <sequencer2.h>
#include <sequencer3.h>
#include <sequencer4.h>
#include <Wire.h>                //enable I2C.

#define HUM_address 111          //default I2C ID number for EZO Humidity sensor.
#define O2_address 108           //default I2C ID number for EZO O2 sensor.
#define CO2_address 105          //default I2C ID number for EZO CO2 sensor.

//EZO-HUM vars
//   | |
//   V V
char computerdata[32];           //we make a 32 byte character array to hold incoming data from a pc/mac/other.
byte received_from_computer = 0; //we need to know how many characters have been received.
byte serial_event = false;       //a flag to signal when data has been received from the pc/mac/other.
byte code = 0;                   //used to hold the I2C response code.
char Humidity_data[22];          //we make a 22-byte character array to hold incoming data from the Humidity sensor.
byte in_char = 0;                //used as a 1 byte buffer to store inbound bytes from the Humidity  sensor.
byte i = 0;                      //counter used for Humidity_data array.
int time_ = 1000;                 //used to set the delay needed to process the command sent to the EZO Humidity sensor.

//EZO-CO2 vars
//   | |
//   V V
//char CO2_computerdata[20];           //we make a 20 byte character array to hold incoming data from a pc/mac/other.
byte CO2_received_from_computer = 0; //we need to know how many characters have been received.
byte CO2_serial_event = false;       //a flag to signal when data has been received from the pc/mac/other.
byte CO2_code = 0;                   //used to hold the I2C response code.
char CO2_data[20];               //we make a 20-byte character array to hold incoming data from the Co2 sensor.
byte CO2_in_char = 0;                //used as a 1 byte buffer to store inbound bytes from the Co2 sensor.
byte CO2_i = 0;                      //counter used for Co2_data array.
//int CO2_time_ = 1000;                 //used to set the delay needed to process the command sent to the EZO Co2 sensor.
int Co2_int;                     //int var used to hold the value of the Co2.

//EZO-O2 vars
//   | |
//   V V
//char O2_computerdata[20];           //we make a 20 byte character array to hold incoming data from a pc/mac/other.
byte O2_received_from_computer = 0; //we need to know how many characters have been received.
byte O2_serial_event = false;       //a flag to signal when data has been received from the pc/mac/other.
byte O2_code = 0;                   //used to hold the I2C response code.
char O2_data[20];                //we make a 20-byte character array to hold incoming data from the o2 sensor.
byte O2_in_char = 0;                //used as a 1 byte buffer to store inbound bytes from the o2 sensor.
byte O2_i = 0;                      //counter used for o2_data array.
//int O2_time_ = 600;                 //used to set the delay needed to process the command sent to the EZO o2 sensor.

char *HUM;                       //char pointer used in string parsing.
char *TMP;                       //char pointer used in string parsing.
char *NUL;                       //char pointer used in string parsing (the sensor outputs some text that we don't need).
char *DEW;                       //char pointer used in string parsing.
char *O2_reading;
char *O2_reading_2;

float HUM_float;                 //float var used to hold the float value of the humidity.
float TMP_float;                 //float var used to hold the float value of the temperatur.
float DEW_float;                 //float var used to hold the float value of the dew point.
float O2_float;
float CO2Con_float;

void setup()                    //hardware initialization.
{
  Serial.begin(9600);           //enable serial port.
  Wire.begin();                 //enable I2C port.
  while(!Serial);            //wait for serial monitor to be open
}

void serialEvent() {                                                              //this interrupt will trigger when the data coming from the serial monitor(pc/mac/other) is received.
  received_from_computer = Serial.readBytesUntil(13, computerdata, 22);           //we read the data sent from the serial monitor(pc/mac/other) until we see a <CR>. We also count how many characters have been received.
  computerdata[received_from_computer] = 0;                                       //stop the buffer from transmitting leftovers or garbage.
  serial_event = true;                                                            //set the serial event flag.
}

void loop() {                                                                     //the main loop.
  if (serial_event == true) {                                                     //if a command was sent to the EZO device.
    for (i = 0; i <= received_from_computer; i++) {                               //set all char to lower case, this is just so this exact sample code can recognize the "sleep" command.
      computerdata[i] = tolower(computerdata[i]);                                 //"Sleep" ≠ "sleep"
    }
    i=0;                                                                          //reset i, we will need it later

 //---------------------------------------------------------EZO-HUM Sensor-----------------------------------------------------------------------------//
    Wire.beginTransmission(HUM_address);                                              //call the circuit by its ID number.
    Wire.write(computerdata);                                                     //transmit the command that was sent through the serial port.
    Wire.endTransmission();                                                       //end the I2C data transmission.

// Need to talk to each sensor separately. Because they're all Atlas Scientific EZO sensors, they all respond to the same commands

    if (strcmp(computerdata, "sleep") != 0) {                                     //if the command that has been sent is NOT the sleep command, wait the correct amount of time and request data.
                                                                                //if it is the sleep command, we do nothing. Issuing a sleep command and then requesting data will wake the Humidity  sensor.

      delay(time_);                                                               //wait the correct amount of time for the circuit to complete its instruction.

      Wire.requestFrom(HUM_address, 22, 1);                                           //call the circuit and request 22 bytes.
      code = Wire.read();                                                         //the first byte is the response code, we read this separately.

      switch (code) {                       //switch case based on what the response code is.
        case 1:                             //decimal 1.
          Serial.println("HUM Success");        //means the command was successful.
          break;                            //exits the switch case.

        case 2:                             //decimal 2.
          Serial.println("HUM Failed");         //means the command has failed.
          break;                            //exits the switch case.

        case 254:                           //decimal 254.
          Serial.println("HUM Pending");        //means the command has not yet been finished calculating.
          break;                            //exits the switch case.

        case 255:                           //decimal 255.
          Serial.println("HUM No Data");        //means there is no further data to send.
          break;                            //exits the switch case.
    }

    while (Wire.available()) {              //are there bytes to receive.
      in_char = Wire.read();                //receive a byte.
      Humidity_data[i] = in_char;           //load this byte into our array.
      //Serial.println((int)in_char);
      i += 1;                               //incur the counter for the array element.
      if (in_char == 0) {                   //if we see that we have been sent a null command.
        i = 0;                              //reset the counter i to 0.
        break;                              //exit the while loop.
      }
    }
    if (computerdata[0] == 'r') string_pars();    //uncomment this function if you would like to break up the comma separated string into its individual parts.
  }

 //---------------------------------------------------------EZO-O2 Sensor-----------------------------------------------------------------------------//

    Wire.beginTransmission(O2_address);                                           //call the circuit by its ID number.
    Wire.write(computerdata);                                                     //transmit the command that was sent through the serial port.
    Wire.endTransmission();                                                       //end the I2C data transmission.

    if (strcmp(computerdata, "sleep") != 0) {                                     //if the command that has been sent is NOT the sleep command, wait the correct amount of time and request data.
                                                                                //if it is the sleep command, we do nothing. Issuing a sleep command and then requesting data will wake the Humidity  sensor.

      delay(time_);                                                               //wait the correct amount of time for the circuit to complete its instruction.

      Wire.requestFrom(O2_address, 22, 1);                                           //call the circuit and request 22 bytes.
      O2_code = Wire.read();                                                         //the first byte is the response code, we read this separately.

      switch (O2_code) {                       //switch case based on what the response code is.
        case 1:                             //decimal 1.
          Serial.println("O2 Sensor Success");        //means the command was successful.
          break;                            //exits the switch case.

        case 2:                             //decimal 2.
          Serial.println("O2 Sensor Failed");         //means the command has failed.
          break;                            //exits the switch case.

        case 254:                           //decimal 254.
          Serial.println("O2 Sensor Pending");        //means the command has not yet been finished calculating.
          break;                            //exits the switch case.

        case 255:                           //decimal 255.
          Serial.println("O2 Sensor No Data");        //means there is no further data to send.
          break;                            //exits the switch case.
    }

    while (Wire.available()) {              //are there bytes to receive.
      O2_in_char = Wire.read();                //receive a byte.
      O2_data[i] = O2_in_char;           //load this byte into our array.
      Serial.println((int)O2_in_char);
      Serial.println(O2_data);
      i += 1;                               //incur the counter for the array element.
      if (O2_in_char == 0) {                   //if we see that we have been sent a null command.
        i = 0;                              //reset the counter i to 0.
        break;                              //exit the while loop.
      }
    }
//    Serial.print("O2 Concentration:");                      //This code doesn't output any information, although the program receives bytes which display in the while loop.
//    Serial.println(O2_data);
//    Serial.println();

    if (computerdata[0] == 'r') O2_string_pars();             //This code also doesn't output any information.
  }

 //---------------------------------------------------------EZO-CO2 Sensor-----------------------------------------------------------------------------//

    Wire.beginTransmission(CO2_address);                                          //call the circuit by its ID number.
    Wire.write(computerdata);                                                     //transmit the command that was sent through the serial port.
    Wire.endTransmission();                                                       //end the I2C data transmission.

    if (strcmp(computerdata, "sleep") != 0) {                                     //if the command that has been sent is NOT the sleep command, wait the correct amount of time and request data.
                                                                                //if it is the sleep command, we do nothing. Issuing a sleep command and then requesting data will wake the Humidity  sensor.

      delay(time_);                                                               //wait the correct amount of time for the circuit to complete its instruction.

      Wire.requestFrom(CO2_address, 22, 1);                                           //call the circuit and request 22 bytes.
      CO2_code = Wire.read();                                                         //the first byte is the response code, we read this separately.

      switch (CO2_code) {                       //switch case based on what the response code is.
        case 1:                             //decimal 1.
          Serial.println("CO2 Sensor Success");        //means the command was successful.
          break;                            //exits the switch case.

        case 2:                             //decimal 2.
          Serial.println("CO2 Sensor Failed");         //means the command has failed.
          break;                            //exits the switch case.

        case 254:                           //decimal 254.
          Serial.println("CO2 Sensor Pending");        //means the command has not yet been finished calculating.
          break;                            //exits the switch case.

        case 255:                           //decimal 255.
          Serial.println("CO2 Sensor No Data");        //means there is no further data to send.
          break;                            //exits the switch case.
    }

    while (Wire.available()) {              //are there bytes to receive.
      CO2_in_char = Wire.read();                //receive a byte.
      CO2_data[i] = CO2_in_char;           //load this byte into our array.
      //Serial.println((int)CO2_in_char);
      i += 1;                               //incur the counter for the array element.
      if (CO2_in_char == 0) {                   //if we see that we have been sent a null command.
        i = 0;                              //reset the counter i to 0.
        break;                              //exit the while loop.
      }
    }
    Serial.print("CO2 Concentration:");
    Serial.println(CO2_data);
  }

  serial_event = false;                     //reset the serial event flag

//  if (computerdata[0] == 'r') string_pars();    //uncomment this function if you would like to break up the comma separated string into its individual parts.
}
   }

void string_pars() {                        //this function will break up the CSV string into its 3 individual parts. HUM|TMP|DEW.
                                            //this is done using the C command “strtok”.

  HUM = strtok(Humidity_data, ",");         //let's pars the string at each comma.
  TMP = strtok(NULL, ",");                  //let's pars the string at each comma.
  NUL = strtok(NULL, ",");                  //let's pars the string at each comma (the sensor outputs the word "DEW" in the string, we dont need it.
  DEW = strtok(NULL, ",");                  //let's pars the string at each comma.

  Serial.println();                          //this just makes the output easier to read by adding an extra blank line.

  Serial.print("HUM:");                      //we now print each value we parsed separately.
  Serial.println(HUM);                       //this is the humidity value.

  Serial.print("Air TMP:");                  //we now print each value we parsed separately.
  Serial.println(TMP);                       //this is the air temperatur value.

  Serial.print("DEW:");                      //we now print each value we parsed separately.
  Serial.println(DEW);                       //this is the dew point.
  Serial.println();

  //uncomment this section if you want to take the values and convert them into floating point number.
  /*
    HUM_float=atof(HUM);
    TMP_float=atof(TMP);
    DEW_float=atof(DEW);
  */
}

void O2_string_pars() {                        //this function will break up the CSV string
                                            //this is done using the C command “strtok”.

  O2_reading = strtok(O2_data, ",");         //let's pars the string at each comma.
//  O2_reading_2 = strtok(NULL, ",");

  Serial.println();                          //this just makes the output easier to read by adding an extra blank line.

  Serial.print("O2 Concentration: ");
  Serial.println(O2_reading);
//  Serial.println("O2 extra info: ");
//  Serial.print(O2_reading_2);

}

The following is the output from the program:

HUM Success
HUM:45.39
Air TMP:23.61
DEW:11.16
O2 Sensor Success
50
48
46
56
53
0
O2 Concentration:
CO2 Sensor Success
CO2 Concentration:599

Because in your code you are specifically printing the integers?

If you read the program, I am printing the array containing the bytes in the line below the command to print the individual bytes as they are entered into O2_data. These prints output blank lines. I tried replicating the EZO-HUM's string_pars() function for the EZO-O2's outputs, which also outputs blanks. I don't have this issue with either of the other two sensors.

What is i at the start of your receiving loop?

If you mean at the start of the "EZO-O2 Sensor" section, it has been reset to 0 after receiving a NULL command from the EZO-HUM sensor at the end of that sensor's respective section. At least, that's how I'm reading it.

Are you sure of that? Print what i is to make certain.

I printed i in all three segments - HUM, O2, and CO2. The counter did not reset after the HUM segment, but it did after the O2 segment. This was related to the way the EZO-HUM's example code was written. It asked for a 22-byte character from the sensor, resetting the array counter when receiving a "0" byte. Long story short, 22 bytes would cut off the NULL command sent by the sensor, and changing 'Wire.requestFrom(HUM_address, 22, 1);' to 'Wire.requestFrom(HUM_address, 23, 1);' fixed it. Thank you @Majenko !

note: use the name computer_data to have a consistent naming convention throughout your program

You are relying on a NULL byte being received to reset your i pointer variable. If that NULL never arrives for whatever reason you won't be writing your new data to the start of your next array.
You should always reset the counter before receiving new data regardless of what you have just received.


text:
AccelStepper help - it just won't move!
I should begin by saying I am not a programmer, do not really know much about programming, and am programming an Arduino Uno for the first time. I am using a Nema 23 motor (23HS22-2804S) with a microstep driver (ST-M5045). Within the following code is the description of what I need the program to do:
#include <AccelStepper.h>

/* Using a stepper motor,
 rotate a vibrational model using gears interconnected by springs
 in such a way as to induce torsional vibration, which should be visible by comparing
 movement of juxtaposed rotating gears with markers painted on. */

AccelStepper stepper(AccelStepper::FULL4WIRE, 2, 6, 4, 8);

int Microstepping = 8; /* Microstepping factor, as set on the ST-M5045 control board.
                          Multiplies the number of steps per revolution on the stepper motor.
                          Reference controller manual for adjustments to this number. */
int Steps = 200; /* Number of steps on your stepper motor.*/
int SPS;
int Amp;
int Freq;
// int SC;
int n = 2;
int i;
int totalSteps = Microstepping * Steps;

/* It should be noted that the Microstepping and Steps factors are not necessary, and adjusting the microstepping factor
 *  on the fly will not break the code. However, be aware that changing the microstepping factor by more than one interval
 *  at a time can cause the motor to not keep up with the sudden changes, i.e. losing torque or vibrating/stuttering. */

void setup() {               // THIS RUNS ONCE //

  // read potentiometers; raw inputs from 0 to 1023 //
  SPS = analogRead(0)*0.733; // MAX RPM ~28, max speed ~750 steps per sec (speeds above 1000 steps per second are unreliable,
                             // according to AccelStepper documentation)//
  Amp = analogRead(1)/20;     // MAX AMP ~51//
  Freq = analogRead(2)/170;   // MAX FREQ ~6 Hz//

  stepper.setMaxSpeed(SPS);
  stepper.setAcceleration(SPS/1.5);

  int nextStop = totalSteps/Freq;

  stepper.moveTo(nextStop);
  stepper.run();
}

void loop() {
  int nextStop = totalSteps/Freq;

// reaches here, doesn't execute if loop.
   if(stepper.distanceToGo()== 0){
     SPS = analogRead(0)*0.733;
     Amp = analogRead(1)/20;
     Freq = analogRead(2)/170;
     i = SPS - Amp;
     if(i <=0)
       i = 1;
     stepper.setSpeed(i);
     stepper.moveTo(nextStop*n);
     stepper.run();
    }
    n++;
}

When I use Serial.println() to check where the program is working and where it isn't, I see that it completes the setup loop without ever moving, and in slightly different versions of the same code, it has entered the if() statement and executed it (also without moving.)
An earlier version of the program runs and executes all statements, but only moves a maximum of about 20 steps per second, without the fluctuations in speed I call for, and doesn't respond in real time to any input from the speed potentiometer that puts the speed above 20.
Ideally, the program would run the demo at full speed, and freq times per second, it would slow down just enough to be noticeable as a torsional vibration.
I have tried running the program with and without the run() lines, and I have tried using runToNewPosition() in attempts to get the program to stop and properly execute the movement.
I made the setup loop as close as possible to the setup loop in bounce.pde, the example program in the AccelStepper documentation which moves the stepper motor between two points repeatedly, accelerating and decelerating before changing directions. The reason I did this is because I know that the setup loop in bounce.pde works, and so I would feel more confident that my setup loop is not the root problem.
Any help you can offer me is appreciated! Thanks for your time.

That driver appears to use a STEP / DIR interface. You'll need the DRIVER MotorInterfaceType, not FULL4WIRE.

towe, thank you for your response. As I began writing up this post, I began to realize that I am indeed using a driver between the Arduino and the stepper, which I had mistakenly taken to mean a special type of motor with only 2 wires, citing the AccelStepper documentation, which says "2 driver pins required." I'll try editing my program to use the DRIVER interface type.

Please read the documentation for the AccelStepper library.

Poll the motor and step it if a step is due, implementing
accelerations and decelerations to achieve the target position. You
must call this as frequently as possible, but at least once per
minimum step time interval, preferably in your main loop. Note that
each call to run() will make at most one step, and then only when a
step is due, based on the current speed and the time since the last
step.

source
You are only calling run once, after setting a new position.
Move stepper.run(); out of the if statement, the the end of the loop function.
      ...
      stepper.moveTo(nextStop*n);
    }
    stepper.run();
    n++;
}

Thank you for your answer. I have read the documentation a few times, and the description for the run() command means nothing to me because I have no clue what my step time interval is. Like I said, I don't know anything about these things.

run checks if the motor needs to make a (single) step, right now. If not, it just does nothing. You don't need to know when to call it. It will itself keep track of when a new step is needed. So you need to call it as often as possible. I know it isn't all that intuitive. I still find it a bit weird, but I understand why they did it.

Okay, thank you. I've run the program now with the edit you suggested, and it works. Doesn't achieve my end goal yet, but it's on its way.

@czar1249 If this solved your issue, please accept the answer.

source: Stack Exchange

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

sort: votes


text:
Why did it blow up?
I recently designed a PCB to hold an Arduino Nano, IMU and other components. I'm using this platform as the fly computer of a homemade drone. This is one of my first PCB designs and I'm not an expert, so perhaps I'm missing something obvious here.
Now let us get to the problem. I started by testing each component, the Arduino (CPU), CPU + IMU, CPU + HC-05, CPU + HC-05 + RTX(RC receiver). At this last point, the Arduino stopped responding, the RX TX and POW LEDs stay ON all the time. I can't upload new software to it.
I noticed that the ATmega328 was extremely hot! I tried powering the Arduino from the +5V and same result (LEDs stuck ON).
During testing, I had a 3SLiPo battery connected to the PW(top right) of the PCB, and the Arduino was also connected to my PC through the USB port.
Do you see any issues with the PCB design itself?
List of the components tested:

Arduino NANO
HC-05
FlySky receiver
R1 1k
R2 2K
C1 10uF

Thanks.

how much current does the RTX need for operating?

@chrisl Something like 40mA

Do you see any issues with the PCB design itself? -- Aside from the too-thin power traces and terrible grounding? No, nothing jumps out at me...

You say: "3SLiPo battery connected to the PW(top right) of the PCB, and the Arduino was also connected to my PC through the USB port."  I would be suspicious you are driving the power from 2 different sources.  There is a diode in the Nano between the USB's power and 5V Regulator.  But I still would only use one power source at a time.

@Majenko I didn't even think of making the power traces wider, thats a good idea for future PCBs. Regarding the grounds, how would you improve that?

Generally speaking, people usually "flood" the ground.

Yep, @st2000 has it right. A single near-solid ground fill that covers everything is the normal way - then ground connections are just "thermal" connections to that plane.

@st2000 Yeah not sure why I did that. Also having mixed grounds from the battery and the USB doesn´t sound great.

Again, generally, all grounds need to be tied together.  I should add that, generally, all grounds should connect at a single point (flooding will probably get you there).  Not looped around the board (which is usually thought of as bad because of ground loops, trace resistance & noise).

Thanks for your comments, I'm tempted to try this again (without the two power sources) before redesigning the PCB.

May I ask, why the HC's Tx/Rx are not connected to the arduinos serial? And what's the purpose of R1 and R2?

The HC-05 is surely connected to SoftwareSerial. And the resistors are a voltage divider, because the HC-05 needs 3.3V logic level at it's RX.

@SimSon Sure, I do a lot of debugging using the USB port and also I update the code often, so I didn't want to be unplugging the HC05 all the time. As chrisl said, those resistors are used to reduce the voltage into the HC RX (it expects 3.3V not 5).

For higher currents, a DC-DC converter (or if you really want to save every gram one provided by either of the 4 ESCs) might be a good idea.
I don't see any additional problem with the PCB either, but the code could explain what happened. Maybe you initialized the wrong pin as an output?
One more thing to check: my Nano clones have AMS1117-5.0 as an LDO, but its pinout is different than a non-AMS one. If the manufacturer loaded the other one into the machine for that batch, that could cause trouble (but only if someone used it from VIN). Just look at the trace from VIN to the LDO to be sure.

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


text:
Pro Micro ATMEGA32U4 unable to upload
I have a simple flashing led program that I want to upload on my pro micro (see image) but it doesnt work (see image: no port available, Couldn't find a Board on the selected port. Check that you have the correct port selected.  If it is correct, try pressing the board's reset button after initiating the upload.)
I have successfully uploaded this program on my arduino uno.
Ive followed this guide for the drivers and more.
https://learn.sparkfun.com/tutorials/pro-micro--fio-v3-hookup-guide/installing-windows
Thanks for help

Your board will only present a serial port if the sketch that is running on it is programmed to present a serial port. The board does not have an actual serial port for communication with the PC - only what the sketch provides.
If the sketch doesn't provide one, or if the sketch isn't running (for example if it was compiled for the wrong board by accident) then you will never see a serial port.
Since the "normal" way of resetting the board to enter the bootloader (which does present its own serial port) is to open the serial port at 1200 baud, since you don't have one to open it's kind of hard to get to the bootloader. However, depending on what bootloader you have installed there are a number of options that can help you:

Briefly connecting RST to GND just before uploading may activate the bootloader for a few seconds.
Doing the above twice in rapid succession may activate the bootloader for longer (depending on the bootloader version)

Erasing the chip and reinstalling the bootloader is the only real way that is guaranteed to work, though. But that said, I have seen boards come out of China without any bootloader at all - so reinstalling the bootloader is always a good first option with cheap boards.  You can use your Arduino UNO as an ISP programmer (using the ArduinoISP sketch and treating it like you're making a breadboard Arduino).

I have also problem with China boards, after 3 days of googling and trying get boards to work, I found out, that chip it self have difference.one chip is for bootloader from arduino micro, and one from lilypad arduino USB, it is about chip ID when arduino IDE is calling for upload sketch, thers are two 4bit id when it cals. And one is chip with cristal 16MHz lilypad arduino USB, and another version 8MHz Arduino micro, but board is it self looks like Arduino pro micro, Chip type have only few letters difference, if I will never find out that solution, if I will not have two chip comparisions .
Last row of numbers makes chip type difference and vendor id depends to what chip type we have. And what clock speed is using. And I see on the veb that many peoples have this problem to not be able to upload simple sketch because of that chip model.


text:
Not getting any output from ECG sensor AD8232
I am trying for the beginning to run a simple Arduino code in order to test the functionality of the ECG sensor. What I am getting on the output are some random values around 600 or around 200.
I connected everything the same as in any tutorial about AD8232:
GND -> GND, 3.3V -> 3.3V, L0+ -> digital pin 10, L0- -> digital pin 11, output -> analog pin A0.
I placed the sensor pads on my body like in pictures (forming a triangle), but regardless of putting the electrodes or not, I always get the same floating signal.
Here is Arduino code:
int ecg;

void setup() {
  // put your setup code here, to run once:
  Serial.begin(9600);
  pinMode(10,INPUT);
  pinMode(11,INPUT);

}

void loop() {
  if((digitalRead(10) == 1)||(digitalRead(11) == 1)){
    Serial.println('!');
  }
    else{
    // send the value of analog input 0:
    Serial.println(analogRead(A0));
    }
    //Wait for a bit to keep serial data from saturating
    delay(1);
}

When I run this code I get only "!" on the output, no matter where I put the electrodes on my body. When I comment "if" and "else" parts of the code and print directly only reading from the pin A0, I get those random floating values, like on the image.

I also tried another custom built ECG sensor, but the results are the same. I haven't found the solution anywhere. It is not about the noise, because when I touch the metal box of my PC, I only reduce the values but there is still nothing on the output.

I only reduce the values but there is still nothing on the output.
Have you tried measuring using a laptop that isn't connected to AC? Not to mention, have you added large electrolytic capacitors to the 3.3V bus and made sure it can supply enough current for the sensor?

It is OK to accept your own answer as a solution to the problem. I think you get 15 rep for it.

The problem was that I connected GND on the other half of the protoboard and there was no connection. I thought that the whole length of the protoboard is on the same potential for + and -, so GND wasn't connected. After connecting GND pin correctly, all worked perfectly.


text:
Monitoring Power Down Using Arduino UNO and ZMPT101B
I am in the process of implementing power down alerting system suing Arduino UNO and ZMPT101B Single phase relay.
My code as follows,
#include <Filters.h> //Easy library to do the calculations

float testFrequency = 50;                     // test signal frequency (Hz)
float windowLength = 40.0/testFrequency;     // how long to average the signal, for statistist

int Sensor = 0; //Sensor analog input, here it's A0

float intercept = -0.04; // to be adjusted based on calibration testing
float slope = 0.0405; // to be adjusted based on calibration testing
float current_Volts; // Voltage

unsigned long printPeriod = 1000; //Refresh rate
unsigned long previousMillis = 0;

void setup() {
    Serial.begin( 9600 );    // start the serial port
}

void loop() {

    RunningStatistics inputStats;                //Easy life lines, actual calculation of the RMS requires a load of coding
    inputStats.setWindowSecs( windowLength );

    while( true ) {
        Sensor = analogRead(A0);  // read the analog in value:
        inputStats.input(Sensor);  // log to Stats function

        if((unsigned long)(millis() - previousMillis) >= printPeriod) {
            previousMillis = millis();   // update time every second

            Serial.print( "\n" );

            current_Volts = intercept + slope * inputStats.sigma(); //Calibartions for offset and amplitude
            current_Volts= current_Volts*(40.3231);                //Further calibrations for the amplitude

            Serial.print( "\tVoltage: " );
            Serial.print( current_Volts ); //Calculation and Value display is done the rest is if you're using an OLED display

            if (current_Volts <229) {
                test_loop();
            }
        }
    }
}

void test_loop(){
    Serial.print( "Warning!! Server Room Power Down" );
    delay(1000);
}

I am getting the correct voltage reading. When power down it says power down. But when power got up, it still shows power down with older reading. I think the reason for this because my code unable to stop the loop. And if I remove the delay (1000) in test_loop function it works, But my intention to use this sms alerting system and for that I need this delay to stop unnecessary alerts.
My code for SMS Alerting,
Serial.print( "\tVoltage: " );
Serial.print( current_Volts ); //Calculation and Value display is done the rest is if you're using an OLED display

if (current_Volts <229) {
    SendMessage();
}

void test_loop() {
    mySerial.println("AT+CMGF=1");    //Sets the GSM Module in Text Mode
    delay(1000);  // Delay of 1000 milli seconds or 1 second
    mySerial.println("AT+CMGS=\"xxxxxxxxx\"\r"); // Replace x with mobile number
    delay(1000);
    mySerial.println("Warning!! Server Room Power Down");
    delay(100);
    mySerial.println((char)26);// ASCII code of CTRL+Z
    delay(150000);
    mySerial.println("AT+CMGD=2");
}

This code works for the very first outage but after power up also it send power down. First part of serial priniting in test_loop code of Serial.print is used for debugging.

Got a answer for the issue,
Attaching code for anyone interested.
/*
   Design by Vinod Amarathunga 26.08.2018
   FSSG R&D Team
*/

#include <OneWire.h>
#include <DallasTemperature.h>
#include <SoftwareSerial.h>
#define ONE_WIRE_BUS 2
SoftwareSerial mySerial(11, 10); //SIM800L Rx Tx
char msg;
String textMessage;

bool D7_alarmSent = false;
bool Temp_alarmSent = false;

OneWire oneWire(ONE_WIRE_BUS);

DallasTemperature sensors(&oneWire);

void setup()
{
  mySerial.begin(9600);   // Setting the baud rate of GSM Module
  Serial.begin(9600);    // Setting the baud rate of Serial Monitor (Arduino)
  delay(100);
}

void PowerSMS()
{
  Serial.println("Warning!! Server Room Power Down");
  mySerial.println("AT+CMGF=1");    //Sets the GSM Module in Text Mode
  delay(1000);  // Delay of 1000 milli seconds or 1 second
  mySerial.println("AT+CMGS=\"No1\"\r");
  delay(1000);
  mySerial.println("Warning!! Server Room Power Down");
  mySerial.println((char)26);// ASCII code of CTRL+Z
  delay(1000);
  mySerial.println("AT+CMGD=2");

  mySerial.println("AT+CMGF=1");    //Sets the GSM Module in Text Mode
  delay(1000);  // Delay of 1000 milli seconds or 1 second
  mySerial.println("AT+CMGS=\"No2\"\r");
  delay(1000);
  mySerial.println("Warning!! Server Room Power Down");
  mySerial.println((char)26);// ASCII code of CTRL+Z
  delay(1000);
  mySerial.println("AT+CMGD=2");

  mySerial.println("AT+CMGF=1");    //Sets the GSM Module in Text Mode
  delay(1000);  // Delay of 1000 milli seconds or 1 second
  mySerial.println("AT+CMGS=\"No3\"\r");
  delay(1000);
  mySerial.println("Warning!! Server Room Power Down");
  mySerial.println((char)26);// ASCII code of CTRL+Z
  delay(1000);
  mySerial.println("AT+CMGD=2");

}

void SendMessage()
{

  Serial.println("Warning!! Server Room Temperature is Critical");

  mySerial.println("AT+CMGF=1");    //Sets the GSM Module in Text Mode
  delay(1000);  // Delay of 1000 milli seconds or 1 second
  mySerial.println("AT+CMGS=\"No1\"\r"); // Replace x with mobile number
  delay(1000);
  mySerial.println("Warning!! Server Room Temperature is Critical");
  mySerial.println(String("Reading : ") + sensors.getTempCByIndex(0) + String("*C"));
  delay(100);
  mySerial.println((char)26);// ASCII code of CTRL+Z
  delay(1000);
  mySerial.println("AT+CMGD=2");

  mySerial.println("AT+CMGF=1");    //Sets the GSM Module in Text Mode
  delay(1000);  // Delay of 1000 milli seconds or 1 second
  mySerial.println("AT+CMGS=\"No2\"\r");
  delay(1000);
  mySerial.println("Warning!! Server Room Temperature is Critical");
  mySerial.println(String("Reading : ") + sensors.getTempCByIndex(0) + String("*C"));
  delay(100);
  mySerial.println((char)26);// ASCII code of CTRL+Z
  delay(1000);
  mySerial.println("AT+CMGD=2");

  mySerial.println("AT+CMGF=1");    //Sets the GSM Module in Text Mode
  delay(1000);  // Delay of 1000 milli seconds or 1 second
  mySerial.println("AT+CMGS=\"No3\"\r");
  delay(1000);
  mySerial.println("Warning!! Server Room Temperature is Critical");
  mySerial.println(String("Reading : ") + sensors.getTempCByIndex(0) + String("*C"));
  delay(100);
  mySerial.println((char)26);// ASCII code of CTRL+Z
  delay(1000);
  mySerial.println("AT+CMGD=2");

}

void loop()
{
  sensors.requestTemperatures(); // Send the command to get temperature readings
  delay(1000);
  Serial.println(String("Temp Reading : ") + sensors.getTempCByIndex(0) + String("*C"));
  Serial.println(String("Voltage Digital: ") + digitalRead(7));
  Serial.println(Temp_alarmSent ? "True" : "False" );
  Serial.println(D7_alarmSent ? "True" : "False" );
  Serial.println("***********");
  ReceiveMessage();

  if (digitalRead(7) == 1 || sensors.getTempCByIndex(0) > 29 || D7_alarmSent == true || Temp_alarmSent == true ) {
    if (digitalRead(7) == 1 ) {
      if (!D7_alarmSent) {
        D7_alarmSent = true;
        PowerSMS();
      }

    }

    else if (sensors.getTempCByIndex(0) > 29 ) {
      if (!Temp_alarmSent) {
        Temp_alarmSent = true;
        SendMessage();
      }

    }

    else {

      if (D7_alarmSent){                  //alarmSent == true means that previous state was "Power Down"
          SendMessage_After_Power_Down();          //Send message
          D7_alarmSent = false;
          Temp_alarmSent = false;             //Reset alarmstate
        }

    }
  }

}

void SendMessage_Normal()
{
  Serial.println("Temperature and Power is OK");

  mySerial.println("AT+CMGF=1");    //Sets the GSM Module in Text Mode
  delay(1000);  // Delay of 1000 milli seconds or 1 second
  mySerial.println("AT+CMGS=\"No1\"\r");
  delay(1000);
  mySerial.println("Temperature and Power is OK");
  mySerial.println(String("Reading : ") + sensors.getTempCByIndex(0) + String("*C"));
  delay(100);
  mySerial.println((char)26);// ASCII code of CTRL+Z
  delay(1000);

  mySerial.println("AT+CMGF=1");    //Sets the GSM Module in Text Mode
  delay(1000);  // Delay of 1000 milli seconds or 1 second
  mySerial.println("AT+CMGS=\"No2\"\r");
  delay(1000);
  mySerial.println("Temperature and Power is OK");
  mySerial.println(String("Reading : ") + sensors.getTempCByIndex(0) + String("*C"));
  delay(100);
  mySerial.println((char)26);// ASCII code of CTRL+Z
  delay(1000);

  mySerial.println("AT+CMGF=1");    //Sets the GSM Module in Text Mode
  delay(1000);  // Delay of 1000 milli seconds or 1 second
  mySerial.println("AT+CMGS=\"No3\"\r");
  delay(1000);
  mySerial.println("Temperature and Power is OK");
  mySerial.println(String("Reading : ") + sensors.getTempCByIndex(0) + String("*C"));
  delay(100);
  mySerial.println((char)26);// ASCII code of CTRL+Z
  delay(1000);

}
void SendMessage_After_Power_Down(){

  Serial.println("Power Back Online");

  mySerial.println("AT+CMGF=1");    //Sets the GSM Module in Text Mode
  delay(1000);  // Delay of 1000 milli seconds or 1 second
  mySerial.println("AT+CMGS=\"No1"\r");
  delay(1000);
  mySerial.println("Power Back Online");
  delay(100);
  mySerial.println((char)26);// ASCII code of CTRL+Z
  delay(1000);

  mySerial.println("AT+CMGF=1");    //Sets the GSM Module in Text Mode
  delay(1000);  // Delay of 1000 milli seconds or 1 second
  mySerial.println("AT+CMGS=\"No2\"\r");
  delay(1000);
  mySerial.println("Power Back Online");
  delay(100);
  mySerial.println((char)26);// ASCII code of CTRL+Z
  delay(1000);

  mySerial.println("AT+CMGF=1");    //Sets the GSM Module in Text Mode
  delay(1000);  // Delay of 1000 milli seconds or 1 second
  mySerial.println("AT+CMGS=\"No3\"\r");
  delay(1000);
  mySerial.println("Power Back Online");
  delay(100);
  mySerial.println((char)26);// ASCII code of CTRL+Z
  delay(1000);

  }

void ReceiveMessage()
{
  if (mySerial.available() > 0)
  {
    mySerial.println("AT+CNMI=2,2,0,0,0"); // AT Command to recieve a live SMS
    delay(1000);
    textMessage = mySerial.readString();
    Serial.print(textMessage);
    delay(10);
  }
  if (textMessage.indexOf("Status") >= 0) {
    SendMessage_Normal();
    mySerial.println("AT+CMGD=2");

  }
}

It is OK to accept your own answer as the solution.


text:
Sending Data Between Arduino Nano and D1 Mini
I am sending data from Arduino Nano to D1 Mini,
Transmitter is Arduino Nano
Transmitter Code:
#include <DES.h>
#include <SoftwareSerial.h>
SoftwareSerial link(2, 3); // Rx, Tx
DES des;
byte in[8];
String  input;
char text[20];
char charVal[6];
char buf[30];
void setup() {
  link.begin(9600);
  Serial.begin(9600);
  Serial.println("Hello! Pleace Enter Your Data to Encrypt");
}
void tdesTest() {
  byte out[8];
  byte key[] = {
    0x3b, 0x38, 0x98, 0x37, 0x15, 0x20, 0xf7, 0x5e, // key A
    0x92, 0x2f, 0xb5, 0x10, 0xc7, 0x1f, 0x43, 0x6e, // key B
    0x3b, 0x38, 0x98, 0x37, 0x15, 0x20, 0xf7, 0x5e, // key C (in this case A)
  };
  Serial.println();
  Serial.println("====== Triple-DES test ======");
  //encrypt
  Serial.print("Encrypt...");
  unsigned long time = micros();
  des.tripleEncrypt(out, in, key);
  time = micros() - time;
  Serial.print("done. (");
  Serial.print(time);
  Serial.println(" micros)");
  delay(10000);
  printArray(out, link);
  link.write(out, 9);
  delay(2000);
  //decrypt
  for (int i = 0; i < 8; i++)
  {
    in[i] = out[i];
  }
  Serial.print("Decrypt...");
  time = micros();
  des.tripleDecrypt(out, in, key);
  time = micros() - time;
  Serial.print("done. (");
  Serial.print(time);
  Serial.println(" micros)");
  printArray(out);
  delay(2000);
}
//passing output and Print
void printArray(byte output[], Print& serial)
{
  for (int i = 0; i < 8; i++)
  {
    if (output[i] < 0x10)
    {
      Serial.print("0");
    }
    Serial.print(output[i], HEX);
    Serial.print(" ");
    delay(100);
  }

  Serial.println();
}
//printing output without link pass
void printArray(byte output[])
{
  for (int i = 0; i < 8; i++)
  {
    if (output[i] < 0x10)
    {
      Serial.print("0");
    }
    Serial.print(output[i], HEX);
    Serial.print(" ");
    delay(100);
  }
  Serial.println();
}
void userdata() {
  Serial.println("Sending User Data");
  byte user[] = {0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x30};
  printArray(user, link);
  link.write(user, 9);
  delay(100);
  tdesTest();

}
void loop() {
  while (Serial.available() > 0) {
    String  input = Serial.readString(); // read the incoming data as string
    memset(in, 0, 9); // Erase the contents of in[]
    input.toCharArray((char *)in, 9); // Copy up to 8 bytes from the string

    userdata();
  }
}

And receiving same from D1 Mini (ESP8266)
Receiver Code:
//Receiver code
#include <SoftwareSerial.h>
SoftwareSerial link(4, 0); // Rx, Tx

byte greenLED = 13;
byte cString[8];
byte chPos;
byte ch;
byte out[8];
String hexstring = "";

void setup()
{
  link.begin(9600); //setup software serial
  Serial.begin(9600);    //setup serial monitor
  pinMode(greenLED, OUTPUT);
}

void loop()
{

  while (link.available() > 0)
  {
    ESP.wdtDisable(); // This helps th avoid not reciving data after second try

    //read incoming char by char:
    ch = link.read();
    cString[chPos] = ch;
    chPos++;

    digitalWrite(greenLED, HIGH); //flash led to show data is arriving
    delay(20);
    digitalWrite(greenLED, LOW);

  }
  if (ch != 0)
  {
    printArray(cString);
    ESP.wdtEnable(1);
    Serial.flush();
    cString[chPos] = 0; //terminate cString
    chPos = 0;
  }

}

//printing output
void printArray(byte output[])
{
  for (int i = 0; i < 8; i++)
  {
    if (output[i] < 0x10)
    {
      Serial.print("0");
    }
    Serial.print(output[i], HEX);
    hexstring += String(output[i], HEX);
    Serial.print(" ");
    delay(100);

  }
  Serial.println();
  Serial.println("Your String Sir:");
  Serial.print(hexstring);
  Serial.println();
  ch = 0; // Avoid printing 0s when no data is recived
  hexstring = ""; //Clear the memeory of hexstring
}

In Receiver I am receiving data as below:

I want to get data in Single Stream to receiver as Example: 31 30 30 30 30 30 30 30 7E B5 2D 4D 93 CB 08 BA or in receiver join two streams in to a single stream,
On Side Note:
1st Part is Plain Data and 2nd Part will be Encrypted Data
Could anyone please help..

Can't you concat 2 strings? If you would a white space between each byte just concatenate a space. Trivial answer but I'm not sure which your core question is.

How to do that? Transmitter sends two char streams,

Since I don't think concat will work

Why not? You calculate hexstring, which can be concat to the next one.

Could you share me how in my receiver code ?

@fabianoriccardi Still Same Could you help me to fix the issue.

Accidently got deleted previous comment

Actually I don't know how to help you: I can explain what you should do, but I will not write code since I cannot test it.

Yes, Please help me, I will test it.

Managed Get it Working:
Change the Transmitter Code to Cascade Two Char Streams Before Sending:
Transmitter Code:
#include <DES.h>
#include <SoftwareSerial.h>
SoftwareSerial link(2, 3); // Rx, Tx
DES des;
byte in[8];
String  input;

void setup() {
  link.begin(9600);
  Serial.begin(9600);
  Serial.println("Hello! Pleace Enter Your Data to Encrypt");

}

//passing output and Print
void printArray(byte output[], Print& serial)
{
  for (int i = 0; i < 8; i++)
  {
    if (output[i] < 0x10)
    {
      Serial.print("0");

    }
    Serial.print(output[i], HEX);
    Serial.print(" ");
    delay(100);

  }

  Serial.println();

}
//printing output without link pass
void printArray(byte output[])
{
  for (int i = 0; i < 8; i++)
  {
    if (output[i] < 0x10)
    {
      Serial.print("0");

    }
    Serial.print(output[i], HEX);
    Serial.print(" ");
    delay(100);

  }
  Serial.println();
}

void userdata_and_Encrypt() {
  Serial.println("Sending User Data");
  byte username[] = {0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30};
  printArray(username, link);
  byte username_data = (username, 9);
  delay(100);

  byte out[8];
  byte key[] = {
    0x3b, 0x38, 0x98, 0x37, 0x15, 0x20, 0xf7, 0x5e, // key A
    0x92, 0x2f, 0xb5, 0x10, 0xc7, 0x1f, 0x43, 0x6e, // key B
    0x3b, 0x38, 0x98, 0x37, 0x15, 0x20, 0xf7, 0x5e, // key C (in this case A)
  };

  Serial.println();
  Serial.println("====== Triple-DES test ======");
  //encrypt
  Serial.print("Encrypt...");
  unsigned long time = micros();
  des.tripleEncrypt(out, in, key);
  time = micros() - time;
  Serial.print("done. (");
  Serial.print(time);
  Serial.println(" micros)");
  delay(100);
  printArray(out, link);
  byte password_data = (out, 9);
  delay(100);
  byte data_stream = username_data + password_data;
  printArray(data_stream, link);
  link.write(out, 17);

  //decrypt
  for (int i = 0; i < 8; i++)
  {
    in[i] = out[i];
  }
  Serial.print("Decrypt...");
  time = micros();
  des.tripleDecrypt(out, in, key);
  time = micros() - time;
  Serial.print("done. (");
  Serial.print(time);
  Serial.println(" micros)");
  printArray(out);
  delay(100);

}

void loop() {

  while (Serial.available() > 0) {

    String  input = Serial.readString(); // read the incoming data as string
    memset(in, 0, 9); // Erase the contents of in[]
    input.toCharArray((char *)in, 9); // Copy up to 8 bytes from the string

    userdata_and_Encrypt();

  }
}

Receiver Code to Accept 16 Bytes
Receiver Code:
//Receiver code
#include <SoftwareSerial.h>
SoftwareSerial link(4, 0); // Rx, Tx

byte greenLED = 13;
byte cString[8];
byte chPos;
byte ch;
byte out[8];
String hexstring = "";
static String data = "";

void setup()
{
  link.begin(9600); //setup software serial
  Serial.begin(9600);    //setup serial monitor
  pinMode(greenLED, OUTPUT);
}

void loop()
{

  while (link.available() > 0)
  {
    ESP.wdtDisable(); // This helps th avoid not reciving data after second try

    //read incoming char by char:
    ch = link.read();
    cString[chPos] = ch;
    chPos++;

    digitalWrite(greenLED, HIGH); //flash led to show data is arriving
    delay(20);
    digitalWrite(greenLED, LOW);

  }
  if (ch != 0)
  {
    printArray(cString);
    ESP.wdtEnable(1);
    Serial.flush();
    cString[chPos] = 0; //terminate cString
    chPos = 0;
  }

}

//printing output
void printArray(byte output[])
{
  for (int i = 0; i < 16; i++)
  {
    if (output[i] < 0x10)
    {
      Serial.print("0");
    }
    Serial.print(output[i], HEX);
    hexstring += String(output[i], HEX);
    Serial.print(" ");
    delay(100);

  }
  Serial.println();

  Serial.println("Your String Sir:");
  Serial.println(hexstring);

  Serial.println();
  ch = 0; // Avoid printing 0s when no data is recived
  hexstring = ""; //Clear the memeory of hexstring
}

Working Output:


text:
Pass Byte Array to Char and Send to a Separate Arduino
I am trying to send data between Arduino Nano and D1 Mini (ESP 8266 Module)
My Code as below in Nano which will be the transmeting ,
#include <DES.h>
#include <SoftwareSerial.h>
SoftwareSerial link(2, 3); // Rx, Tx
DES des;
byte in[8];
String  input;
char text[20];
char charVal[6];

char buf[30];
void setup() {
  link.begin(9600);
  Serial.begin(9600);
  Serial.println("Hello! Pleace Enter Your Data to Encrypt");

}

void tdesTest() {
  byte out[8];
  byte key[] = {
    0x3b, 0x38, 0x98, 0x37, 0x15, 0x20, 0xf7, 0x5e, // key A
    0x92, 0x2f, 0xb5, 0x10, 0xc7, 0x1f, 0x43, 0x6e, // key B
    0x3b, 0x38, 0x98, 0x37, 0x15, 0x20, 0xf7, 0x5e, // key C (in this case A)
  };

  Serial.println();
  Serial.println("====== Triple-DES test ======");

  //encrypt
  Serial.print("Encrypt...");
  unsigned long time = micros();
  des.tripleEncrypt(out, in, key);
  time = micros() - time;
  Serial.print("done. (");
  Serial.print(time);
  Serial.println(" micros)");
  printArray(out);
  /*
    //decrypt
    for (int i = 0; i < 8; i++)
    {
      in[i] = out[i];
    }
    Serial.print("Decrypt...");
    time = micros();
    des.tripleDecrypt(out, in, key);
    time = micros() - time;
    Serial.print("done. (");
    Serial.print(time);
    Serial.println(" micros)");
    printArray(out);
    delay(2000);
  */
}

//printing output
void printArray(byte output[])
{
  for (int i = 0; i < 8; i++)
  {
    if (output[i] < 0x10)
    {
      Serial.print("0");
    }
    Serial.print(output[i], HEX);
    Serial.print(" ");
    delay(100);

  }
  Serial.println();

}

void loop() {

  while (Serial.available() > 0) {

    String  input = Serial.readString(); // read the incoming data as string
    memset(in, 0, 9); // Erase the contents of in[]
    input.toCharArray((char *)in, 9); // Copy up to 8 bytes from the string
    tdesTest();

  }
}

In printArray(byte output[])I am getting Output as HEX Byte as below

I am trying to send the this encrypted data to from Arduino nano to D1 Mini,
I have wrote a small Receiver  Application in D1 Mini and It works ,
Receiver Code:
//Receiver code
#include <SoftwareSerial.h>
SoftwareSerial link(4, 0); // Rx, Tx

byte greenLED = 13;
char cString[2000];
byte chPos = 0;
byte ch = 0;
char dataStr[6];

void setup()
{
  link.begin(9600); //setup software serial
  Serial.begin(9600);    //setup serial monitor
  pinMode(greenLED, OUTPUT);
}

void loop()
{

  while (link.available())
  {
    ESP.wdtDisable();

    //read incoming char by char:
    ch = link.read();
    cString[chPos] = ch;
    chPos++;

    digitalWrite(greenLED, HIGH); //flash led to show data is arriving
    delay(20);
    digitalWrite(greenLED, LOW);

  }

  cString[chPos] = 0; //terminate cString
  chPos = 0;

  Serial.print(cString);
  ESP.wdtEnable(1);
  Serial.flush();

}

I want to pass this HEX data Generated to D1 Mini from Arduino Nano,
I have wrote test code in Arduino Nano for Transmitter(Nano) and between Receiver (D1 Mini) it works,
//Transmitter Code for Testing Connections
#include <SoftwareSerial.h>
SoftwareSerial link(2, 3); // Rx, Tx
byte greenLED = 12;
char text[20] ;
char charVal[6];

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

}

void loop()
{
  strcat(text, "Message"); //append to empty string
  Serial.println(text); //print to local screen for debug*
  link.println(text);

  delay(10000);
}

Please help me to send this HEX data in single shot to D1 Mini.

You can change your printArray function to work on provided Print instance:
void printArray(byte output[], Print& serial)
{
  for (int i = 0; i < 8; i++)
  {
    if (output[i] < 0x10)
    {
      serial.print("0");
    }
    serial.print(output[i], HEX);
    serial.print(" ");
  }
  serial.println();

}

then you can use it as printArray(out, Serial); or printArray(out, link);.

Thanks for the comment, I have applied your solution like this: link and getting this error link

Please help me to correct it if it's a wrong way I am using

Could you elaborate please ?

Could you show it in the code ?

Thanks, Got it. But Receiver not showing any output. I think this will pass the HEX output as it is, But receiver is expecting Char input.  Any idea how to make it char printArray(out, link);

byte is char, char is byte. you can do link.write(out, 8);

Thanks it worked , But what I am receiving is unreadable link

of course it is unreadable. it is the same array for which you use your printArray to print it.

Could you advise how to make it readable ?

use your printArray function

I have add it as this Code but getting error Error

Could you help me to fix this

No worries, I was bale to fix it.

Thanks for the support, really  appreciated.

Let us continue this discussion in chat.


text:
PIR Sensor Gives False High in 55 Minutes (Can't find a way to solve)
I have built a system to identify motions and fire alerts.
System can send a SMS in case if it's identify such alerts.
System consist of two parts,
Part 1: Armed and Disarmed using a PIN (Using Arduino Uno)
This Module Consists with 4*4 PIN PAD, I2C Module, 2 LEDs and Arduino UNO
This part works fine
Part 2: Sensor Systems and SMS System
This module consists of Arduino NANO, MQ135 Gas Sensor, PIR Sensor, SIM 800L Module, Tamper Switches
This part also works, but in every 55 minutes it generates a false motion alert and I could not troubleshoot the issue.
Schematics is attached.
Codes as Below,
Part 1: Test6-LCD_Intigrated_Working_Temper.ino
#include <Keypad.h>
#include<EEPROM.h>
#include <Wire.h> // Library for I2C communication
#include <LiquidCrystal_I2C.h> // Library for LCD
char password[4];
char pass[4],pass1[4];
int i=0;
int k=0;
char customKey=0;
byte col = 0;
const byte ROWS = 4; //four rows
const byte COLS = 4; //four columns
char keys[ROWS][COLS] = {

{'1','2','3','A'},

{'4','5','6','B'},

{'7','8','9','C'},

{'*','0','#','D'}

};

byte rowPins[ROWS] = {9, 8, 7, 6}; //connect to the row pinouts of the keypad

byte colPins[COLS] = {13, 12, 11, 10}; //connect to the column pinouts of the keypad

//initialize an instance of class NewKeypad

Keypad customKeypad = Keypad( makeKeymap(keys), rowPins, colPins, ROWS, COLS );
LiquidCrystal_I2C lcd = LiquidCrystal_I2C(0x27, 16, 2);
void setup()
{
  lcd.begin();

  Serial.begin(9600);
  pinMode(4, INPUT);      // Tamper Signal
  pinMode(3, OUTPUT); //Armed
  pinMode(2, OUTPUT); //Disarmed

  lcd.setCursor(0, 0);
  lcd.print ("--SECURE ROOM!--");
  Serial.print("Server Room");
  lcd.setCursor(0, 1);
  lcd.print ("PLEASE ENTER PIN");
  Serial.print("\n*********Keypad Lock********* ");
  delay(2000);
  Serial.println("\n*********Enter Ur Passkey:*********");

  for(int j=0;j<4;j++)
    EEPROM.write(j, j+49);
  for(int j=0;j<4;j++)
    pass[j]=EEPROM.read(j);
}

void Armed(){

  digitalWrite(3, HIGH);
  digitalWrite(2, LOW);
  Serial.println("\n***System is Armed***");
  lcd.clear();
  lcd.setCursor(0, 0);
  lcd.print("--SYSTEM ARMED--");
  lcd.setCursor(0, 1);
  lcd.print("-SENSORS ACTIVE-");
  delay (2000);
  lcd.noBacklight();
  i=0;
  customKey=0;

  }

void change()
{
  int j=0;
 lcd.backlight();
  Serial.println("\n*********UR Current Passk*********");
  lcd.clear();
      lcd.setCursor(0, 0);
      lcd.print("   CURRENT PIN   ");

  while(j<4)
  {
    char key=customKeypad.getKey();
    if(key)
    {
      pass1[j++]=key;

      Serial.print(key);
      lcd.setCursor(j+6, 1);
      lcd.print(key);

    }
    key=0;
  }
  delay(500);

  if((strncmp(pass1, pass, 4)))
  {

    Serial.println("\n*********Wrong Passkey*********");
    lcd.clear();
    lcd.setCursor(0, 0);
      lcd.print("  UNAUTHORIZED  ");

    Serial.println("\n*********UNAuthorized Access*********");
      lcd.setCursor(0, 1);
      lcd.print(" ACCESS  DENIED ");
    delay(10000);
  }
  else
  {
    j=0;

    Serial.println("\n*********Enter New Passk: *********");
      lcd.clear();
      lcd.setCursor(0, 0);
      lcd.print(" ENTER NEW PIN! ");

    while(j<4)
    {
      char key=customKeypad.getKey();
      if(key)
      {
        pass[j]=key;

        Serial.print("*");
        EEPROM.write(j,key);
        lcd.setCursor(j+6, 1);
        lcd.print(key);
        j++;

      }
    }

    Serial.println("*********Done*********");
    lcd.clear();
      lcd.setCursor(0, 0);
      lcd.print("----UPDATED!----");
    delay(1000);
  }

  Serial.println("\n*********Enter Ur Passk: *********");
  lcd.clear();

      lcd.setCursor(2, 0);
      lcd.print ("SECURE ROOM!");
      lcd.setCursor(0, 1);
      lcd.print ("PLEASE ENTER PIN");
      lcd.noBacklight();
  customKey=0;
}

void tamper(){
  Serial.println("\n***System is Tampered***");
  lcd.clear();
  lcd.setCursor(2, 0);
  lcd.print("--TAMPERED--");
  lcd.setCursor(0, 1);
  lcd.print("WARN COMPROMISED");
  delay (2000);
  lcd.backlight();
  i=0;
  customKey=0;

  }

void loop()
{
  Serial.println(digitalRead(4));
  customKey = customKeypad.getKey();
  if(customKey=='A')
    Armed();

    if(customKey=='C')
    change();
   /*
    if(digitalRead(4)==LOW)
    tamper();
 */
  if (customKey)
  {
    lcd.backlight();
    password[i++]=customKey;

    Serial.print("*");
    lcd.setCursor(0, 0);
    lcd.print("    PIN INPUT    ");
    lcd.setCursor(0,1);
    lcd.print("       ----     ") ;
    lcd.setCursor(i+6, 1);
    lcd.print("*");

      }

  if(i==4)
  {
    delay(200);
    for(int j=0;j<4;j++)
      pass[j]=EEPROM.read(j);
    if(!(strncmp(password, pass,4)))
    {

      Serial.println("\n*********Passkey Accepted*********");
    lcd.clear();
    lcd.setCursor(0, 0);
    lcd.print("---AUTHORIZED---");
    lcd.setCursor(0, 1);
    lcd.print("SYSTEM  DISARMED");

      delay(1000);
      digitalWrite(2, HIGH);
      digitalWrite(3, LOW);
      i=0;

    }
    else
    {

      Serial.println("\n*********Access Denied*********");
      lcd.clear();
      lcd.setCursor(0, 0);
      lcd.print("  UNAUTHORIZED  ");
      lcd.setCursor(0, 1);
      lcd.print(" ACCESS  DENIED ");

      delay (5000);

      Serial.println("\n*********Enter Passkey: *********");
      lcd.clear();
      lcd.setCursor(0, 0);
      lcd.print ("--SECURE ROOM!--");
      lcd.setCursor(0, 1);
      lcd.print ("PLEASE ENTER PIN");
      lcd.noBacklight();

      i=0;

    }
  }
}

Part 2: Test7_Tested_Tamper_Smoke_PIR_GSM.ino.ino
/*
    Arduino with PIR motion sensor and MQ 135 Smoke Detector with SMS Alert
    Developed By Vinod Amarathunga 18.09.2019
    DMS Electronics (Pvt) Ltd
*/

#include <SoftwareSerial.h>
SoftwareSerial mySerial(6, 5); //SIM800L Rx Tx
char msg;
String textMessage;

int smokeA0 = A0;            // MQ135 Analog Input
int led = 13;                // the pin that the LED is atteched to
int priState = LOW;             // by default, no motion detected
int TampSignal = 11;       // Tamper 5V Signal
int sensorThres = 150; //Smoke Air Quality Threshold
int pretamper = LOW;
bool premotion = false;
bool prefire = false;

void setup() {
  pinMode(led, OUTPUT);      // initalize LED as an output
  pinMode(3, INPUT);    // initialize sensor as an input
  pinMode(TampSignal, OUTPUT); // Tamper Drive Signal as Output
  pinMode(10, INPUT);    // Tamper Alert
  Serial.begin(9600);        // initialize serial
  mySerial.begin(9600);
}

void SmokeSMS()
{
  Serial.println("Warning!! Secure Room Fire Detected");
  mySerial.println("AT+CMGF=1");    //Sets the GSM Module in Text Mode
  delay(1000);  // Delay of 1000 milli seconds or 1 second
  mySerial.println("AT+CMGS=\"+xx\"\r");
  delay(1000);
  mySerial.println("Warning!! Secure Room Fire Detected");
  mySerial.println((char)26);// ASCII code of CTRL+Z
  delay(1000);
  mySerial.println("AT+CMGD=2");

  delay(5000);

  Serial.println("Warning!! Secure Room Fire Detected");
  mySerial.println("AT+CMGF=1");    //Sets the GSM Module in Text Mode
  delay(1000);  // Delay of 1000 milli seconds or 1 second
  mySerial.println("AT+CMGS=\"+xx2\"\r");
  delay(1000);
  mySerial.println("Warning!! Secure Room Fire Detected");
  mySerial.println((char)26);// ASCII code of CTRL+Z
  delay(1000);
  mySerial.println("AT+CMGD=2");

}

void MotionSMS()
{
  Serial.println("Warning!! Secure Room Motion Detected");
  mySerial.println("AT+CMGF=1");    //Sets the GSM Module in Text Mode
  delay(1000);  // Delay of 1000 milli seconds or 1 second
  mySerial.println("AT+CMGS=\"xx\"\r");
  delay(1000);
  mySerial.println("PIN 3 HIGH");
  mySerial.println((char)26);// ASCII code of CTRL+Z
  delay(1000);
  mySerial.println("AT+CMGD=2");

  delay(5000);
/*
  Serial.println("Warning!! Secure Room Motion Detected");
  mySerial.println("AT+CMGF=1");    //Sets the GSM Module in Text Mode
  delay(1000);  // Delay of 1000 milli seconds or 1 second
  mySerial.println("AT+CMGS=\"xx2\"\r");
  delay(1000);
  mySerial.println("Warning!! Secure Room Motion Detected");
  mySerial.println((char)26);// ASCII code of CTRL+Z
  delay(1000);
  mySerial.println("AT+CMGD=2");
*/

}

void TamperSMS()
{

  Serial.println("Warning!! System Tamper Detected");
  mySerial.println("AT+CMGF=1");    //Sets the GSM Module in Text Mode
  delay(1000);  // Delay of 1000 milli seconds or 1 second
  mySerial.println("AT+CMGS=\"xx2\"\r");
  delay(1000);
  mySerial.println("Warning!! System Tamper Detected");
  mySerial.println((char)26);// ASCII code of CTRL+Z
  delay(1000);
  mySerial.println("AT+CMGD=2");

  delay(5000);

  Serial.println("Warning!! System Tamper Detected");
  mySerial.println("AT+CMGF=1");    //Sets the GSM Module in Text Mode
  delay(1000);  // Delay of 1000 milli seconds or 1 second
  mySerial.println("AT+CMGS=\"xx\"\r");
  delay(1000);
  mySerial.println("Warning!! System Tamper Detected");
  mySerial.println((char)26);// ASCII code of CTRL+Z
  delay(1000);
  mySerial.println("AT+CMGD=2");

}

void loop() {
  int analogSensor = analogRead(smokeA0);
  digitalWrite(TampSignal, HIGH); // Drive Signal Always High
  //val = digitalRead(3);   // read sensor value
  //  ReceiveMessage(); //System Recive Messages
  //Serial.print("Smoke Level:");
  //Serial.println(analogSensor);
  Serial.println(digitalRead(3));
  if (analogSensor > sensorThres  ) {           // check if the sensor is HIGH and Armed Status
    digitalWrite(led, HIGH);   // turn LED ON
    Serial.print("\nSmoke Alert....!!!");
    SmokeSMS(); // Smoke SMS Alert
    delay(100);                // delay 100 milliseconds

  }

  else if ( priState == LOW && digitalRead(3) == HIGH && digitalRead(7) == HIGH ) {

    digitalWrite(led, HIGH);   // turn LED ON
    Serial.println("Motion detected!");
    MotionSMS(); //Motion SMS
    priState = HIGH; // Previous Motion Status set to High

    delay(15000);

  }

  else if ( digitalRead(7) == HIGH && digitalRead(10) == LOW )
  {

    digitalWrite(led, HIGH);   // turn LED ON and Temper Alarm On
    Serial.println("One of the TIP Switches being Trigered");
    if ( pretamper == LOW ) {
      TamperSMS(); // Tamper SMS
      pretamper  = HIGH;
      delay(15000);
    }

  }

  else {
    digitalWrite(led, LOW); // turn LED OFF
    digitalWrite(11, HIGH); // Tamper Signal
    delay(200);             // delay 200 milliseconds
    pretamper = LOW;
    //Serial.print("\n.....Normal.....");

    if (priState == HIGH) {
      Serial.println("Motion stopped!");
      priState = LOW;       // update variable state to LOW

    }
  }

}

I am loosing my mind because I could not find the problem of getting false alert in every 55 minutes.
I am very grateful any one can help.

I see nothing in the code that could cause a signal exactly every 55 minutes. -- Is it possible to detach the motion sensor from the NANO, to try out if the signal also appears stand alone. Eventually you attach the Data output of the sensor to a bi stable flip flop, that drives an LED. To find out if the motion detector triggers e.g a test signal every 55 minutes. You could also try to hide the sensor from ambient light. Perhaps there is a light source that flashes IR light every 55 minutes and interferes with the sensor in any way.

Hi @PeterPaulKiefer, Thanks. Actually there is no light emits in every 55 minute. I am testing it in a closed box. I am going to try it in a stand alone as suggested. But I am in a doubt hot to get the alert to inspect

If you still get no findings then, it would be helpful to see the Serial print outs of at least two different test runs. i.e power the alarm system wait 3 x 55 minutes (so the false trigger happens 3 times).  Switch the power off wait 30 minutes and do the same again. The output must contain timestamps.  That 55 minutes interval is really strange. I would be interesting if these are relative intervals or absolute time points, hence the second test run.

After tons of research found a way to solve this issue.
This is common for ordinary PIR sensors when we use the 5V out from Arduino.
Therefore we have to separate the power for PIR and the Arduino using a Opto Coupler and some transistors to smooth the signal.
Now the solution works fine.
I am posting here to help someone stuck with same issue.


text:
counting revolution of incremental encoder
I'm doing a project which requires me to use an faulhaber encoder,and the one i have is a 2channel 16lines per revolution.
I haven't worked with encoders before and based on what i found the lines per revolution mean how many pulses i get for each revolution and so in my code i used an interrupt and counted the times my channel A changed till it got to 32 counting once for every high to low and once for every low to high for my 16 pulses which then by my belief means that I've had one revolution but when i test the code after around like 1/6 of a spin my counter reaches 32 and I'd appreciate if someone can tell me where I'm going wrong with this .
This is the datasheet of the encoder I'm using IE2_16 .
here is the code :
volatile long int ticks = 0 ;
unsigned long int rev = 0 ;
const int channelA = 2 ;
void setup(){
   Serial.begin(9600);
   pinMode(6,OUTPUT);
   pinMode(7,OUTPUT);
   pinMode(8,OUTPUT);
   pinMode(channelA,INPUT);
   attachInterrupt(digitalPinToInterrupt(channelA), numCunts,  CHANGE);
   digitalWrite(7,LOW);
   digitalWrite(8,HIGH);
   analogWrite(6,15);
}
void loop(){
       Serial.println(rev);

    if(ticks>=32){
       ticks = 0;
       rev++;

      }
}

void numCunts(){
  ticks+=1 ;
  }

No, there are several problems with your decoding. First, you are detecting every change. You want to detect only rising or falling edge changes.
Second, the changes are likely noisy, so you need to write your decoder to "debounce" the readings. With a 2-channel encoder like you're using, the usual way to do that is to only respond to rising edge changes on channel A after you've seen a rising edge change on channel B, and visa-versa.
See this link for a description of how they work: http://www.creative-robotics.com/quadrature-intro
I tried my hand at writing my own decoder, but it's harder than you might think to get it right. I'd suggest using somebody else's rotary encoder library.
And a quick google search revealed this library on github: https://github.com/PaulStoffregen/Encoder
(I don't know if it's any good or not. It's the first hit I found.)


text:
why data value is 0
i want to apply formula. but getting 0 at output.

#include "HX711.h"
int data;
HX711 scale(A1, A0);		// parameter "gain" is ommited; the default value 128 is used by the library

void setup() {
  Serial.begin(38400);

  scale.set_scale(2280.f);
  scale.tare();

}

void loop() {
  Serial.print("one reading:\t");
  data==(scale.get_units()/10);
  Serial.println(data);

		        // put the ADC in sleep mode
  delay(500);

}

why do you have == in data==(scale.get_units()/10);?

It's zero because you never assign it a value.
Here you are comparing the current value of data (0) with the results of your calculation:
data==(scale.get_units()/10);

I think you intended to use the assignment, not comparison, operator =:
data = (scale.get_units()/10);


text:
Getting wrong value from sd card
I stored "28328630" in sd card but at output i getting wrong value.
on serial "5566" getting this value.

#include "HX711.h"
#include <Wire.h>
#include <LiquidCrystal_I2C.h>
#include <SPI.h>
#include <SD.h>
int data = 0;
int curr_rate = 0;  // current flow rate in L/M

File dataFile;
HX711 scale(A1, A0);
LiquidCrystal_I2C lcd(0x3F, 16, 2);  // set the LCD address to 0x27 for a 16 chars and 2 line display
const int buttonPin = 8;
int total;
int buttonState = 0;
void setup()
{
  lcd.init();
  lcd.init();
  lcd.backlight();

  lcd.setCursor(0, 0);
  lcd.print("KWALITY PVT.LTD.");
  Serial.begin(38400);

  while (!Serial)
  {
    ; // wait for serial port to connect. Needed for native USB port only
  }
  Serial.print("Initializing SD card...");

  // see if the card is present and can be initialized:
  if (!SD.begin(4))
  {
    Serial.println("Card failed, or not present");
    // don't do anything more:
    // return;
  }
  Serial.println("card initialized.");

  // open the file. note that only one file can be open at a time,
  // so you have to close this one before opening another.
  File dataFile = SD.open("datalog.txt"); //<<<<<<<<<<<<<< set the name

  // if the file is available, write to it:
  if (dataFile)
  {
    while (dataFile.available())
    {
      Serial.write(dataFile.read());      //<<<<<<<<<<<<< remove
      total = total + dataFile.parseInt();  //<<<<<<<<<<<<<<<< new
    }
    lcd.clear();
    dataFile.close();
    Serial.print("Total: ");
    lcd.setCursor(0, 1);
    lcd.print("Total:");
    Serial.println(total);
    lcd.setCursor(6, 1);
    lcd.print(total);
    Serial.print("Value in sd card 28328630....");
  }
  // if the file isn't open, pop up an error:
  else {
    Serial.println("error opening file");
  }

  scale.set_scale(2280.f);
  scale.tare();

}

void loop()
{
  buttonState = digitalRead(buttonPin);
  dataFile = SD.open("datalog.txt", FILE_WRITE);

  if (buttonState == HIGH) {

    if (scale.get_units() > 10 && scale.get_units() < 200)
    {

      //SET1
      lcd.setCursor(0, 0);
      lcd.print("LPM: ");
      lcd.setCursor(5, 0);
      data = (scale.get_units() / 10);
      lcd.print(data);
      scale.power_down();
      delay(5000);
      scale.power_up();

    //  scale.power_down();
      delay(60000);
     // scale.power_up();
      lcd.clear();

      if (dataFile) {
        Serial.print("Writing to datalog.txt...");
        dataFile.println(data);
        // close the file:
        dataFile.close();
        Serial.println("done.");
      } else {
        // if the file didn't open, print an error:
        Serial.println("error opening test.txt");
      }

      curr_rate = (data + total);
      Serial.print("Total: ");
      lcd.setCursor(0, 1);
      lcd.print("TOTAL:");
      lcd.setCursor(7, 1);
      lcd.print(curr_rate);

    }
    else
    {
      lcd.setCursor(0, 0);
      lcd.print("LPM: ");
      lcd.setCursor(5, 0);
      lcd.print("000   ");
      delay(500);
      lcd.print("        ");

      if (dataFile) {
        Serial.print("Writing to datalog.txt...");
        dataFile.println("0");
        // close the file:
        dataFile.close();
        Serial.println("done.");
      } else {
        // if the file didn't open, print an error:
        Serial.println("error opening test.txt");
      }

    }
  }
  else {
    lcd.setCursor(0, 0);
    lcd.print("     SENSOR    ");
    lcd.setCursor(0, 1);
    lcd.print("  DISCONNECTED  ");
    delay(2000);
    lcd.clear();

  }

}

2 bytes type int can only hold numbers from -32,768 to 32,767. but you have more  issues in you code

https://forum.arduino.cc/index.php?topic=632947.0

i replaced int with long int, on output i get

Total: 8328630
Value in sd card 28328630....

the Serial.write(dataFile.read()); stole the 2 and wrote it as invisible character

you have a lot of unnecessary code in your sketch that has nothing to do with writing to SD card ... reduce your sketch to only write 28328630 and read it back


text:
Use Arduino as transmitter and receiver UART
I know UART and serial communication model and data frame. But I want to ask about something else, when I searched in internet just found examples of one Arduino as (receiver) and another Arduino as (transmitter).
So my question is how can I implement two Arduino and both of arduinos can communicate each other when after transferring data from one to another
(example A->B). If the interpretation of the received data has to be forwarded to the first sender again(B->A).

UART is full duplex. It has 2 lines, one for sending, 1 for receiving. So this is automatically implemented

So can you give me an code sample, in one Arduino acting differently in transmitting or receiving moments?

If you know how to make A talk to B then you already know how to make B talk to A - it's exactly the same.

But how should call transmit and receive function in main function? Just separate with delay? Or after transmit data should switch my position as receiver until the data come in?

You sure now Serial.write() and Serial.read(). That's already what you want. A hint to make it clear to you: When using the common Serial.print() function only the RxD line is in charge an thus only "half" of the serial interface is used. If you connect TxD of arduino A to RxD of another arduino B and RxD to TxD respectively you have full-duplex communication which is what you're asking.

Oh gotcha. So I just should use write and read functions for full duplex. Print is for half duplex. You saved my day man. Thank you

I recommend looking for a simple example to see how the reading actually has to be implemented. This tutorial might help you: https://robotic-controls.com/learn/arduino/arduino-arduino-serial-communication

No, print is not only for half duplex. The whole connection is always duplex, and you can send and receive at any time. print and write are doing nothing else but putting the data into the buffer. The transmitting is done in the background by the Serial library and the hardware. And all read commands are just reading data, that was already received, from the buffer. If you want one arduino to react to the other, just read the data from the first Arduino on the second, and let it send corresponding data back directly (you don't need a delay there)

@chrisl hmm, was your comment meant to be a reply to the OP's comment in the question? Otherwise, what exactly of what I wrote is incorrect? You can Serial.print() without RxD connected. I'm aware of the routine executed in hardware, but I think that info doesn't help the OP very much at this point.

Your answer isn't wrong. I wanted to answer to ghe OPs comme t above, since it seemed to me, that he thinks, he cannot use print if he wants to communicate in both directions. I wanted to prevent a misunderstanding. And it is always good to know, what the called functions really do. That helps in understanding. If this is too complex for a comment, I can also write an answer, to explain it better, than in my comment


text:
power 12v solenoid from DC jack of Arduino Uno
I was wondering if it is possible to power up a 12V solenoid valve from the DC jack of the Arduino Uno, provided that I'm powering the Arduino from the same jack:

the Arduino is kind of irrelevant to the question ... make a Y cable instead of soldering to the connector ... cut the existing cable and splice a pigtail into it

i would use a dc jack Y adapter instead of splicing the wire, but whatever's clever should suffice.

Thank you everyone for your comments, I was just afraid of frying my setup

Sure, that's the same as if you were directly soldering a second plug to your power supply. Just make sure the power supply delivers enough current for your solenoid (the power used by the Arduino will be comparably negligible).


text:
3.5mm jack frequency response at low frequency (20Hz)
I'm trying to drive a bass shaker at low frequencies, down to 20Hz, with an Arduino. Has anyone ever done something like this?
I found an audio amp that takes in 3.5mm aux, and I was hoping to get a 3.5mm jack to drive the amp from an Arduino. However, I can't find any technical specs on audio jacks so I am not sure if they support low frequencies. Are there any audio jacks with frequency response data available?
If not, are there other ways to achieve this?

why the doubt? how did you get the idea that it would be a problem?

I have read that using aux to feed subwoofers is not recommended since many audio devices filter out low frequencies on aux outputs

but that is not a property of the jack, but a property of the amplifier. so the answer doesn't help you at all

You can send DC (i.e. 0 Hz) through an audio jack, so I would not worry about its low-frequency response.

OP meant a jack input of the amplifier, not the connector itself


text:
If Arduino digital pins can be used as power supply pins then why do we need VCC pins?
If Arduino digital pins can be used as power supply pins then why do we need VCC pins?
VCC pins work the same as digital outputs , don't they? So why do we still need VCC pins to
power components

Digital IO pins and Vcc are very different.
When using the digital IO functionality of a pin, the pin is connected to the  digital IO hardware inside the microcontroller. This hardware is a driver, that can drive the pin to either LOW or HIGH (0V or Vcc) depending on a bit in a register. Though this driver can only provide a very limited amount of current. The absolute maximum is specified as 40mA peak, but you should not exceed 20mA continuously. So technically you can power a component from a digital pin (just like you can drive an LED through a digital pin), but only if it does NOT draw over 20mA. That is a rather small current. So in general nobody would recommend doing that. If you draw too much current from a digital pin, you can destroy its IO hardware.
The Vcc pin is the power input for the microcontroller on the board. The microcontroller needs this to be at the right voltage (5V for the Arduino Uno), to work properly. This power can come from different sources: The voltage regulator (via barrel jack or Vin), USB or directly provided through the Vcc pin. As long as the voltage stays in the correct range, it will work.
You can utilize the Vcc pin to power external components. Though this is just connecting these components to the power supply in parallel with your microcontroller. The current for the components will not be drawn through the microcontroller, but only through the copper traces on the board from your power source. That is also the reason why the power output of the Vcc pin cannot be controlled via software: It is just directly electrically connected to the power source of the microcontroller. Nothing in between.

So: Don't power anything other than components with really small current draw from IO pins. If you do it, always make sure beforehand that the current will be small enough (below 20mA).
If the components need more current, you can power them through the Vcc pin. Only use the IO pins for control in that case. For some components (like motors, bright LED lights, etc) you might need additional hardware for controlling them (like a transistor/MOSFET/driver chip).
And keep in mind, that the current through the Vcc pin is also limited. Depending on your power source you can draw up to 1A (including the Arduino itself) from the voltage regulator on a genuine Arduino. If you need to draw more current than that, you need to connect the components to a power source outside of the Arduino. For example you can connect them to the power source, that you connected to the Arduino directly, so that the high current doesn't need to flow through the Arduino, but can directly go to the high power components.


text:
float miscalculation when int32_t variable is divided by 10
i want to ask, how to get correct float value from uint32_t or long variable is devided by 10??
long var3 = 1139399025;
int a = 3;
int b = 10;
void setup() {
  Serial.begin(9600);
  Serial.println((float)a/b,2);
  Serial.println((float)var3/b,2);
}
void loop() {
}

result
0.3
113939904.00

it give 113939904.00 instead of 113939902.50, plase how to fix that?

what is the value of var3 when it is converted to float?

long var3 = 1139399025;

Floats have only limited precision see: https://cdn.arduino.cc/reference/en/language/variables/data-types/float/ . You get better precision using a double but only on a 32 bit Arduino (Due etc.). However there will still be some loss of precision.

I use arduino mega 2560

1139399025 is not a floating point number: the largest odd integer that
can be exactly represented as a float is
224 − 1 = 16777215. Then, when var3 is
cast to float, it gets rounded to the closest float, which
is 1139399040. This is quite a small error, especially considering
that, in this range, only multiples of 128 can be exactly
represented as floats.
Dividing 1139399040 by 10 gives 113939904, which happens to be a float.
The floating point division gives then the exact result, which is what
gets printed. Indeed, floating point operations do not always give
inexact results: sometimes they are exact. However, unless you know what
you are doing, exact results only happen by luck. In general, expect
each floating point operation to make a relative rounding error in the
range of 10−7.
A highly recommended read: What Every Programmer Should Know About
Floating-Point Arithmetic.
Edit: If you want to print the value of an integer divided by 10,
you can divide the number using Euclidean division. Print the
quotient, then the decimal point, then the remainder:
Serial.print(var3 / 10);  // quotient
Serial.print('.');
Serial.println(var3 % 10);  // remainder

As these are all integer operations, there is no rounding error
involved. Obviously this trick doesn't work for arbitrary divisors.

So what should i do?

@mukhlas: Do not use floats.

@mukhlas Or use double that provide more significant digits, for this specific case. But in any case you need to understand floating-point, as Edgar suggested.

@thebusybee: The AVR microcontrollers (or rather, their port of GCC) do not support double precision floats: their double type is implemented as float32, just like float.

Oh, really? Well, then, no luck. :-(

Thanks you all :)


text:
Use Arduino MEGA generate 40kHz multiple square wave signal with 10 phase
I want to use Arduino-mega generate multiple square wave signal,the siganl is 40kHz and it can be used to drive ultrasonic transducer.
So,I use the trategy in article "Ultraino: An Open Phased-Array System for
Narrowband Airborne Ultrasound Transmission",which apply 10 bit signal with sequence of '0' or '1' in PORTA,PORTC...etc to get a square wave signal like Fig 1.

Fig.1 square wave signal

Then I change the sequence pattern to shift phase,and just only 10 phases,some problem happen.
I am curious about the principle of this method:

Why the sequence can generate signal with 40kHz?Does it mean Arduino will cost serval microseconds executing command like POTRA=0x1. I try to change the length of the array,it will no longer generate the square wave well.

When I execute the shift function shiftPhase,it have 10 phase.In 5 phase it will move the square wave like Fig.2,the other 5 phase will be like Fig3,the duty of square wave is changed,just like inverted.So,how does it happen,just with change the sequence of 0,1?

Fig.2 shift wave success

Fig.3 shift wave failed

the code I use is:
#include <avr/sleep.h>
#include <avr/power.h>
#define N_PATTERNS 1
#define N_PORTS 10
#define N_DIVS 10
#define COMMAND_SWITCH 0b00000000
#define COMMAND_DURATION 0b00110000
#define MASK_DURATION 0b00111111
#define COMMAND_COMMITDURATIONS 0b00010000

#define WAIT(a) __asm__ __volatile__ ("nop")
#define OUTPUT_WAVE(pointer, d)  PORTA = pointer[d*N_PORTS + 0]; PORTC = pointer[d*N_PORTS + 1]; PORTL = pointer[d*N_PORTS + 2]; PORTB = pointer[d*N_PORTS + 3]; PORTK = pointer[d*N_PORTS + 4]; PORTF = pointer[d*N_PORTS + 5]; PORTH = pointer[d*N_PORTS + 6];  PORTD = pointer[d*N_PORTS + 7]; PORTG = pointer[d*N_PORTS + 8]; PORTJ = pointer[d*N_PORTS + 9]
static byte bufferA[N_PATTERNS * N_DIVS * N_PORTS];
static byte bufferB[N_PATTERNS * N_DIVS * N_PORTS];
static byte animation[100] = {
                            0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
                            0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
                            0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
                            0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
                            0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
                            0xff,0xff,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
                            0xff,0xff,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
                            0xff,0xff,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
                            0xff,0xff,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
                            0xff,0xff,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
                            };

String str="";
void shiftPhase(byte* p,int len,int inter,int stepsize,byte id)
{
  byte mask=0xff-id;
  byte q[10]={0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0};
  for(int i=0;i<10;i++)
  {
    q[i]=p[i*inter];
  }
  for(int i=0;i<10;i++)
  {
    p[i*inter]=(q[(i+stepsize+10)%10]&id)|(mask&q[i]);
  }
}

void setup()
{
  //set as output ports A C L B K F H D G J
  DDRA = DDRC = DDRL = DDRB = DDRK = DDRF = DDRH = DDRD = DDRG = DDRJ = 0xFF;
  //low signal on all of them
  PORTA = PORTC = PORTL = PORTB = PORTK = PORTF = PORTH = PORTD = PORTG = PORTJ = 0x00;
  //clear the buffers
  for (int i = 0; i < (N_PATTERNS * N_DIVS * N_PORTS); ++i) {
    bufferA[i] = bufferB[i] = 0;
  }
   for (int i = 0; i < 100; ++i)
   {
      bufferA[i] =  animation[i];
   }

  // disable everything that we do not need
  ADCSRA = 0;  // ADC
  power_adc_disable ();
  power_spi_disable();
  power_twi_disable();
  power_timer0_disable();
  power_usart1_disable();
  power_usart2_disable();

  Serial.begin(9600);

  byte bReceived = 0;
  bool byteReady = false;
  bool emittingA = true;
  byte* emittingPointerH = & bufferA[0];
  byte* emittingPointerL = & bufferA[N_PORTS * N_DIVS / 2];

LOOP:
  OUTPUT_WAVE(emittingPointerH, 0);
  OUTPUT_WAVE(emittingPointerH, 1);
  OUTPUT_WAVE(emittingPointerH, 2);
  OUTPUT_WAVE(emittingPointerH, 3);
  OUTPUT_WAVE(emittingPointerH, 4);
  OUTPUT_WAVE(emittingPointerL, 0);
  OUTPUT_WAVE(emittingPointerL, 1);
  OUTPUT_WAVE(emittingPointerL, 2);
  OUTPUT_WAVE(emittingPointerL, 3);
  OUTPUT_WAVE(emittingPointerL, 4);

  byteReady = Serial.available();
  if(byteReady!=0)
  {
      str="";
      str=char(Serial.read());
      Serial.println(str);
      if(str=="1")
      {
        shiftPhase(bufferA,10,10,1,0x1);
      }
      if(str=="2")
      {
        shiftPhase(bufferA,10,10,-1,0x1);
      }
    }
 while(Serial.read()>=0){}
  goto LOOP;

}

void loop() {}

Thanks a lot!
The code of the article can be see in link.

Off topic: PORTA = PORTB = ... = PORTG = ... = 0xFF; is really bad idea. The PORTG has only 6 bits and according to the datasheet, unused pins are read as 0. And this pattern assing to right most port, then reads the value and assigns it to next one

Shiny100 asked:

Does it mean Arduino will cost several microseconds executing command
like POTRA=0x1.

I tried compiling POTRA=0x1 and I got this:
ldi r24, 0x01  ; load 0x1 into register r24
out 0x02, r24  ; output register r24 to PORTA (I/O address 0x02)

These are both single cycle instructions, so the sequence takes
2 cycles, i.e. 0.125 µs at 16 MHz. Your code, however,
does a lot more that that. The macro OUTPUT_WAVE() involves reading
ten values from RAM and writing them to ten different ports. The first
call to this macro gets compiled into this:
lds r24, 0x028D ; r24 = bufferA[0]
out 0x02, r24   ; PORTA = r24
lds r24, 0x028E ; r24 = bufferA[1]
out 0x08, r24   ; PORTC = r24
lds r24, 0x028F ; r24 = bufferA[2]
sts 0x010B, r24 ; PORTL = r24
lds r24, 0x0290 ; r24 = bufferA[3]
out 0x05, r24   ; PORTB = r24
lds r24, 0x0291 ; r24 = bufferA[4]
sts 0x0108, r24 ; PORTK = r24
lds r24, 0x0292 ; r24 = bufferA[5]
out 0x11, r24   ; PORTF = r24
lds r24, 0x0293 ; r24 = bufferA[6]
sts 0x0102, r24 ; PORTH = r24
lds r24, 0x0294 ; r24 = bufferA[7]
out 0x0b, r24   ; PORTD = r24
lds r24, 0x0295 ; r24 = bufferA[8]
out 0x14, r24   ; PORTG = r24
lds r24, 0x0296 ; r24 = bufferA[9]
sts 0x0105, r24 ; PORTJ = r24

The out instruction is still single cycle, but lds (load from
memory) and sts (store to memory) take two cycles each. You may notice
that only ports A through F are accessed with the out instruction.
This is because they are mapped in the I/O address space of the
microcontroller. The other four ports are accessed using the slower
sts instruction on memory-mapped addresses.
If you count your cycles, you should get 34 cycles for the whole
sequence, which is 2.125 µs at 16 MHz. Ideally, you would like
this to take 2.5 µs (1/10 of a cycle of a 40 kHz signal). You
may notice that the code you took inspiration from has a few
instructions between successive calls to OUTPUT_WAVE(). It looks to me
like those were carefully timed to get as close as possible to
2.5 µs per phase. This approach is obviously fragile: any tiny
change in the code, or even a compiler upgrade, can throw off your
carefully timed code.
Edit: The second question, if I understand it correctly, is about
the change in duty cycle. The waveforms have a nominal duty cycle of
50%: the signal is LOW over 5 time slots (5/10 of the cycle), then
HIGH for the next 5 time slots. The time slots, however, do not
have all the same length. The first nine last 2.125 µs each. The
last one, however, is somewhat longer, because it takes the duration of
the code handling the serial port, and the two cycles of goto LOOP;.
If the longer time slot happens when the output is HIGH, you get an
actual duty cycle higher than 50%. If it happens when it is HIGH, you
get a shorter duty cycle, like in your “shift wave failed” example.

Thanks,I think I get more clear about it.But I wonder how can I get the compiling information as you do and, can I create more than 24 square wave like this method?

@Shiny100: You can disassemble a .elf file with the command avr-objdump -S. avr-objdump should already be somewhere in your Arduino installation. The method you linked to can drive up to three signals per timer. Using the prescaler reset feature of Timers 0, 1, 3, 4, and 5, you can synchronize those timers and drive up to 13 signals phase-coherently.