text:
Optimal and Safe Water Pump Control
I'm using an Arduino Micro, a 12 V water pump, and a print relay to water a plant.
A water level switch monitors the the water tank to make sure the water pump does not run dry.
I tried different watering times and figured that when using longer watering times of 90,000 milliseconds and longer, the relay sometimes does not switch correctly and the pumps keeps running. I'm not sure if my code is optimal for that kind of purpose:
const int Power_Water = 3; // Pin to turn the Pump On and Off via relay
const int Watering_Time = 90000; // Time the water's supposed to run
const int Water_Tank = 10; // Water Level Switch

void setup() {
  Serial.begin(9600);
  pinMode(Power_Water,OUTPUT); // Pin that triggers the Relay as Output
  pinMode (Water_Tank,INPUT_PULLUP); // Pin of Water_Level Sensor as internal pullup
}

void loop () {
  unsigned long watering_Start = millis();

  while (millis() - watering_Start <= Watering_Time && (digitalRead (Water_Tank) == LOW)) {
    digitalWrite(Power_Water,HIGH); // Water Pump goes ON
    Serial.println(millis() - watering_Start);
  }

  if (millis() - watering_Start > Watering_Time || (digitalRead (Water_Tank) == HIGH)) {
    Serial.println("Pump OFF");
    digitalWrite(Power_Water,LOW);// Water Pump OFF
   }
   delay(100000000); // example "sleep" time the system is not supposed to water
}

Any suggestions are appreciated.
I changed
const int Power_Water = 3; // Pin to turn the Pump On and Off via relay
const long Watering_Time = 90000; // Time the water's supposed to run
const long Water_Tank = 10; // Water Level Switch

void setup() {
  Serial.begin(9600);
  pinMode(Power_Water,OUTPUT); // Pin that triggers the Relay as Output
  pinMode (Water_Tank,INPUT_PULLUP); // Pin of Water_Level Sensor as internal pullup
}

void loop () {
  unsigned long watering_Start = millis();
  digitalWrite(Power_Water,HIGH);
  while (digitalRead(Power_Water) == HIGH) {
    Serial.println(millis() - watering_Start);
    if (millis() - watering_Start > Watering_Time || (digitalRead (Water_Tank) == HIGH)) {
      Serial.println("Pump OFF");
      digitalWrite(Power_Water,LOW);
    }
  }
  delay(100000000); // example "sleep" time the system is not supposed to water
}

you defined  watering_time as an integer .... read this .... https://www.arduino.cc/reference/en/language/variables/data-types/int/  ........ then read this
... https://www.arduino.cc/reference/en/language/variables/data-types/long/

use unsigned long Watering_Time. maximum value for signed int is 32,767

That delay statement totally defeats the purposes of your millis code.  If you want to enforce a minimum off time then you'll have to do that with millis as well.  Using millis in this way requires that you allow the loop function to repeat many thousands of times per second.  As written you only allow the loop function to run through once every eleven and a half days.

thanks for the input... .. thats an example and here I want the code to repeat every  100000000 ms but when the pump starts I want to monitor it with millis.. the watering part is the important part for me.. I think I found the right code for my needs and added it to my question

The right code for you will not have any use of the delay function.  Using the delay function is breaking your use of millis.  Using millis requires that the loop be free to run.  You can't use blocking calls like delay at the same time you are using millis for timing and expect anything to work out.


text:
RF signal boosting
I'm working on a quadcopter project. The quadcopter will be quite autonomous, but sometimes I'll need to send some messages to it. So I built a simple, one-way RF communication system based on two simple 433 MHz modules.
It works, but when the propellers of the quadcopter approach the take-off speed it begins having trouble in receiving the RF messages, and after a certain speed it stops working.
I suppose this is due to the electrical noise produced by the four little brushed motors. Yesterday I increased a little the transmitter's voltage, and that increased a little the minimum antenna-antenna distance with the motors on, but that is far from enough.
What else could I do to increase the transmitter's power?
Thanks in advance
Noè
P.S.: Here are my RF modules:

You might like to read my investigation into those modules (https://hackingmajenkoblog.wordpress.com/2016/11/18/cheap-433mhz-transmitters/) and then rethink using them - instead using something more reliable.

You can add an antenna to the ANT hole. Just add some copper wire. You'd have to experiment with the length of it, to get the best range.

thanks Majenko, I read your investigation. My modules are better built than yours and my rf system is very simple (I only need to send a few dozen of bits per second (and not every second), without any transmission sopeed requirement, andalways in the same direction), but of coure you're right, they're worth 99p. I will change them, but I can't get them in the next few weeks, so for the moment I would like to improve the existing system...

You need something like LoRa modules. I have attached very nice 1/4 wave antennas with radials to these modules, and they still couldn't receive well... Polarity even became an issue. Got 25 meters without obstructions, but the slightest obstruction (leaves even) cut the signal off. Look into LoRa. I will now read @Majenko's blog.

No one uses those for micro aircraft, as 2.4 GHz solutions are both more reliable and lighter weight.  But the minute your quadcopter makes it off the ground, you'll probably discover that you don't have a working flight stabilization firmware.  Spend some time on rcgroups where people who have actually done this (mostly in reflashing cheap toys with custom firmware) discuss the issues.

As has been mentioned adding an antenna to the "ANT" pin on the transmitter will help. You need to get the length right though, but it's easy to calculate.
Best is to use single-core insulated wire (0.6mm is a good choice).
To calculate the right length you first need to know your frequency. Then you convert that to the wavelength, and then cut your wire to a quarter of that length.
Wavelength is c/f where c is the speed of light (in m/s), and f is the frequency.
So for 433MHz you have a wavelength of (299792458/433000000) 0.69m.
A quarter of that is 0.173m (17.3cm), so cut your wire to that and solder it on.
For 315MHz the wavelength is (299,792,458/315000000) 0.95m, so an antenna length of 0.238m or 23.8cm.
This is known (unsurprisingly) as a quarter wavelength antenna and is the most efficient length for a simple wire antenna.
Whether it will be strong enough to penetrate the noise from the motors is anyone's guess.
You can also add small capacitors (0.1µF ceramic) across the terminals of the motor and between the terminals and the body, to absorb some of the EMI which may help to allow more signal through - as shown here.

Tanks again, @Majenko. I already have an antenna, but it's like twice the length you wrote here; i'll cut it. But I just read the post mentioned by Gerben (here): the author says that I sould subtract the coil soldered in the module (I have a coil which is in fact the first part of the external antenna) to this lenght, does this make sense? And what about other types of antenna? Is it possible to connect some kind of more efficient antenna to such a simple rf module?

It is always possible to attach other antennas, yes. A Yagi array (TV antenna) will increase gain at the cost of omnidirection. You should be tackling the motor noise first though. Don't try to overpower it, eliminate it.

But the antenna port requires desoldering the coil. What range and punchiness did you get with your modules? Partnumbers/link?

I have been using RF modules for different projects that involves using motors. And I have never experienced something like that. Since the motors a significant quantity of current to take off, I recommend using another power supply for the electronic part of the drone and use the actual battery just for the motors.

I can't add a second battery (the quadcopter needs to be very lightweight), but the electronic power supply is protected from the electrical noise of the motors. I think the problem is the electromagnetical noise: if it is too strong the rf signal is "hidden" in the noise and the receiver can't detect it... (is that correct?)

source: Stack Exchange

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

sort: votes


text:
How to run servo 180 degrees and stop?
I'm creating a PIR motion sensor doggy door.
The problem I'm having with it is, it runs 3 times, I've figured out how to pause when reaches 180° but not how to stop.
I was thinking I could use detach my servo and attach after a delay of 30,000 and then re-attach return to 0 degrees, then wait for next PIR high.
But I don't know how to code it into what I have or even if it would work.
My code:

/* This code sweeps a servo from 0 degrees to 180 when the PIR sensor detects motion.
   Special thanks goes to the author of the PIR sensor code, whose code helped tremendously
   in the making of this code and Instructable.
   author of PIR sensor code: Kristian Gohlke / krigoo (_) gmail (_) com / http://krx.at
**/

#include <Servo.h>

Servo myservo; //creates a servo object
//a maximum of eight servo objects can be created
int pos = 0; //variable to store servo position
//amount of time we give the sensor to calibrate(10-60 secs according to the datasheet)
int calibrationTime = 30;
//the time when the sensor outputs a low impulse
long unsigned int lowIn;
//the amount of milliseconds the sensor has to be low
//before we assume all motion has stopped
long unsigned int pause = 5000;
boolean lockLow = true;
boolean takeLowTime;
int pirPin = 12; //digital pin connected to the PIR's output
int pirPos = 13; //connects to the PIR's 5V pin

void setup() {
  myservo.attach(4); //attaches servo to pin 4
  Serial.begin(9600); //begins serial communication
  pinMode(pirPin, INPUT);
  pinMode(pirPos, OUTPUT);
  digitalWrite(pirPos, HIGH);
  //give the sensor time to calibrate
  Serial.println("calibrating sensor ");
  for (int i = 0; i < calibrationTime; i++) {
    Serial.print(calibrationTime - i);
    Serial.print("-");
    delay(1000);
  }
  Serial.println();
  Serial.println("done");
  //while making this Instructable, I had some issues with the PIR's output
  //going HIGH immediately after calibrating
  //this waits until the PIR's output is low before ending setup
  while (digitalRead(pirPin) == HIGH) {
    delay(500);
    Serial.print(".");
  }
  Serial.print("SENSOR ACTIVE");
}

void loop() {
  if (digitalRead(pirPin) == HIGH) {
    //if the PIR output is HIGH, turn servo
    /*turns servo from 0 to 180 degrees and back
      it does this by increasing the variable "pos" by 1 every 5 milliseconds until it hits 180
      and setting the servo's position in degrees to "pos" every 5 milliseconds
      it then does it in reverse to have it go back
      to learn more about this, google "for loops"
      to change the amount of degrees the servo turns, change the number 180 to the number of degrees you want it to turn
    **/
    for (pos = 0; pos < 180; pos += 1) {
      //goes from 0 to 180 degrees
      myservo.write(180);
      delay(8000); ////stops motor for 8 seconds
      for (pos = 180; pos >= 90; pos -= 1) {
        // goes from 180 degrees to 0 degrees
        myservo.write(pos); // tell servo to go to position in variable 'pos'
        delay(15); // waits 15ms for the servo to reach the position
      }
      myservo.write(90);
      delay(4000); //stops motor for 4 seconds
      for (pos = 90; pos <= 180; pos += 1) {
        // goes from 0 degrees to 180 degrees
        // in steps of 1 degree
        myservo.write(pos); // tell servo to go to position in variable 'pos'
        delay(15); // waits 15ms for the servo to reach the position
      }
      //to make it go slower, increase the number.
      if (lockLow) {
        //makes sure we wait for a transition to LOW before further output is made
        lockLow = false;
        Serial.println("---");
        Serial.print("motion detected at ");
        Serial.print(millis() / 1000);
        Serial.println(" sec");
        delay(50);
      }
      takeLowTime = true;
    }

    if (digitalRead(pirPin) == LOW) {
      if (takeLowTime) {
        lowIn = millis(); //save the time of the transition from HIGH to LOW
        takeLowTime = false; //make sure this is only done at the start of a LOW phase
      }
      //if the sensor is low for more than the given pause,
      //we can assume the motion has stopped
      if (!lockLow && millis() - lowIn > pause) {
        //makes sure this block of code is only executed again after
        //a new motion sequence has been detected
        lockLow = true;
        Serial.print("motion ended at "); //output
        Serial.print((millis() - pause) / 1000);
        Serial.println(" sec");
        delay(50);
      }
    }
  }
}

Could I also just change the jumper pin on the PIR hardware for a retriggering set high to keep the door open when the dog is there so it won't just close on them?
I'm using this PIR:

Can you add you code rather than link to it.

Sorry that's a blocked site for me.  Hope someone else can help.

Please can you confirm you want you servo to turn to 180 degrees when you PIR sensor sends a high.  You want your servo to wait for 30 seconds and then return to zero?

I've just realised the servo is opening the door, not moving the PIR sensor :)

Please edit your post, post your code, and format the code using the code formatting markdown (four leading spaces). For help see Markdown help. You should be able to do this by selecting the code and pressing Ctrl+K to have your browser do this for you.

Try to restructure the logic in your question also. What do you want to happen when the PIR is triggered. Put it in small (numbered) steps, not in one big sentence.

I haven't been able to compile or test this but I think it should do what you are asking for, or at the very least steer you in the right direction.
// This code waits for a signal from the PIR sensor.
// When the signal is recieved it rotates the servo 180 degrees and waits 30 seconds
// it then rotates the servo back to 0 (to close the door)

#include <Servo.h>

const int ServoIntraStepDelay   =  15;      // Delay between servo steps (ms)
const int ServoAngleStep        =   1;      // The angle by which the servo position is changed every step (degree)
const int ServoAngleMinimum     =   0;      // The min angle of the servo (degrees)
const int ServoAngleMaximum     = 180;      // The max angle of the servo (degree)
const int DoorOpenPeriod        = 30 * 1000;// The time the door will remain open for (ms)
const int DoorClearPoll         = 100;      // The interval betwen polls to the sensor when checking to see if the door is clear(ms)
const int DoorClearPeriod       = 5000;     // The interval that the PIR sensor must report low before closing the door (ms)

const int PIRCalibrationTime    = 30;       //amount of time we give the sensor to calibrate(10-60 secs according to the datasheet) (s)

const int PinPIRData            = 12;       //digital pin connected to the PIR's output
const int PinPIRPower           = 13;       //connects to the PIR's 5V pin
const int PinServoPower         = 4;        // The pin that controls the servo.

Servo myservo;                              //creates a servo object

void setupCalibratePIR()
{
        //give the sensor time to calibrate
    Serial.println("Calibrating sensor ");
    for(int i = 0; i < PIRCalibrationTime; i++)
    {
        Serial.print(PIRCalibrationTime - i);
        Serial.print("-");
        delay(1000);
    }
    Serial.println();
    Serial.println("done");
    //while making this Instructable, I had some issues with the PIR's output
    //going HIGH immediately after calibrating
    //this waits until the PIR's output is low before ending setup
    Serial.print("Waiting for PIR sensor to report low");
    while (digitalRead(PinPIRData) == HIGH)
    {
        delay(500);
        Serial.print(".");
    }
    Serial.print("SENSOR ACTIVE");
}

void turnServo (const int& from, const int& to, const int& step)
{
    for(int pos = from; pos <= to; pos += step)
    {
        myservo.write(pos);
        delay(ServoIntraStepDelay);
    } //to make it go slower, increase the number.
}

// Test the PIR sensor and ensure that it reports low for a specific time
void waitForDoorClear ()
{
    bool doorIsNotClear = true;
    while (doorIsNotClear)
    {
        doorIsNotClear = false;
        for (int doorClear = 0; !doorIsNotClear && (doorClear * DoorClearPoll) < DoorClearPeriod; ++doorClear)
        {   // Poll every few ms and check that the sensor in LOW
            // As soon as it is high this loop will exit which restarts the time that the low signal must been seen for.
            delay (DoorClearPoll);
            doorIsNotClear = (digitalRead(PinPIRData) == HIGH);
        }
    }   // This is potentially an infinite loop.
}

void setup()
{
    Serial.begin(9600);                     // Begins serial communication
    myservo.attach(PinServoPower);          // Connect to the servo object
    pinMode(PinPIRData, INPUT);             // Connect the PIR data
    pinMode(PinPIRPower, OUTPUT);           // Connect the PIR power
    digitalWrite(PinPIRPower, HIGH);        // Turn on the PIR power

    setupCalibratePIR();                    // Calibrate the PIR sensor
}
// attach
void loop()
{

    if(digitalRead(PinPIRData) == HIGH)
    { //if the PIR output is HIGH, turn servo

        turnServo (ServoAngleMinimum, ServoAngleMaximum, ServoAngleStep);
        delay (DoorOpenPeriod - DoorClearPeriod);
        waitForDoorClear ();
        turnServo (ServoAngleMaximum, ServoAngleMinimum, -ServoAngleStep);
    }
}

You weren't that far off.

a bunch of errors
Arduino: 1.6.9 (Windows 7), Board: "Arduino/Genuino Uno"
: In function 'void setupCalibratePIR()':
matt:39: error: 'pirPin' was not declared in this scope
while (digitalRead(pirPin) == HIGH)
^
: In function 'void turnServo(const int&, const int&, const int&)':
matt:49: error: 'os' was not declared in this scope
for(int pos = from; pos <= to; [os += step)
^
matt:49: error: expected ',' before '+=' token
for(int pos = from; pos <= to; [os += step)
^
matt:49: error: expected identifier before '+=' token

Yep, sorry like I said I can't compile it at work. pirPin should be PinPIRData.  os should be pos that will clear those three.

ive figured them out     for(int pos = from; pos <= to; [pos += Step) im guessing step is ServoAngleStep but it says expected ',' before '+=' token  ???

That's the [ I must have hit that key instead of P.  I have updated the code, This time I know it compiles, well in visual studio.

the code runs but it is always open now until power is off only then will it return to 0 degrees ive tried changing the code but it doesnt seem to work for me

Comment out the line in loop() that call waitForDoorClear(). Hopefully the door will now open and close, and it will prove the fault is in waitForDoorClear().  Then we need to work out a better way of detecting it's clear.

I have tried all this matt im using the answer u gave that @Nick Gammon deleted for not being an answer and ive tried adding in new lines that run 180 to 0 even new starts that run starting at 180 and runs to 0 but its not working for me
sorry to the site i cant open chat cause i dont have enough rep

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


text:
What's the difference between all the Software Serial Libraries? Which one is Arduino Nano compatible?
There are so many Software Serial Libraries, what are the differences between them? And which one I can use with my Arduino Nano? For my Arduino Nano I need one Hardware Serial Port and one Software Serial port at a baud rate of 115200.
On which pins of the Arduino Nano can I use the software serial library?

This answer lists the 4 basic choices:

HardwareSerial, always the best.  Simply use the pre-defined Serial variable.  On some Arduinos, there are extra HardwareSerial ports, called Serial1, Serial2, etc.  The Nano only has Serial.
AltSoftSerial, the best of the software serial libraries.  Only one instance is allowed, and it is must be used on one of the Input Capture pins (pins 8 & 9 for a Nano).
My NeoSWSerial is next best.  It works on any two pins, but only at baud rates 9600, 19200 and 38400.
SoftwareSerial is the worst choice.  It works on any two pins, but it is very inefficient.  It disables interrupts for the entire time that a character is being sent OR received, and it cannot do both at the same time (unlike all the other serial choices).  This can interfere with other parts of your sketch, other device communications, or with libraries.

If you could use a slower baud rate, you could keep your debug prints on Serial, and use either AltSoftSerial or NeoSWSerial for your device.
But if you have to use 115200, the only reliable choice is Serial.  Although AltSoftSerial and SoftwareSerial allow that baud rate, they may not send/receive data correctly.
In that case, I would suggest using Serial for the 115200 device.  Unless you are using an ISP, you will have to disconnect the device to upload a new sketch over USB.
Then use AltSoftSerial or NeoSWSerial for your debug statements.  You will need a TTL Serial-to-USB adapter (aka FTDI) on the selected pins to connect to the PC.  The Serial Monitor or other Terminal emulator program will read from that USB COM port.

Is AltSoftSerial the same in performance and characteristics, only that NeoICSerial adds the functionality of what? I did not understand completely. https://github.com/SlashDevin/NeoICSerial

@WilliamRoy, NeoICSerial just adds the attachInterrupt method to AltSoftSerial.  You probably don't need to handle each character in an interrupt.  Just use AltSoftSerial and call the available() and then read() if a char is ready.  Similarly, NeoHWSerial adds the same attachInterrupt feature to the core HardwareSerial.  However, NeoSWSerial is a completely different class (it also has the attachInterrupt feature).

"SoftwareSerial is the worst choice". I think at the moment it is improved, based on Neo. If you have time please update the answer. Thanks!

both NeoSW and AltSoft cannot work with ISR vectors.

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


text:
Why do GPS coordinates fail to save on MySQL database using SIM900?
My project is a vehicle tracking system. I'm using a NEO-6M for GPS and a SIM900 for GPRS. I want to send the GPS coordinates to a MySQL database. I've tested the GPS and it's working well. I've succeeded to send the data to the online MySQL database by manually typing the AT commands on the Arduino Serial Monitor. Now, I would like to put the sending of coordinates in a loop for Arduino to send the coordinates on the database every 3 seconds. But there's no data entering the database. What do you think is the problem here? Here's my code (by the way it has no errors reported):
sendlatlng.ino:
#include <SoftwareSerial.h>
#include "SIM900.h"
#include <TinyGPS.h>
#define pinPowerSIM900 14

TinyGPS gps;
SoftwareSerial ss(10, 11);

uint16_t startAddr = 0x0000;
uint16_t lastAddr;
uint16_t TimeIsSet = 0xaa55;
int currentDay = 0;
int currentMonth = 0;
int currentYear = 0;
int currentHour = 0;
int currentMinute = 0;
float flat, flon;
float previousFlat = 0.0;
float previousFlon = 0.0;
static void smartdelay(unsigned long ms);
static void print_float(float val, float invalid, int len, int prec);
static void print_int(unsigned long val, unsigned long invalid, int len);
static void print_date(TinyGPS &gps);
static void print_str(const char *str, int len);

void setup() {
  pinMode (pinPowerSIM900, OUTPUT); digitalWrite (pinPowerSIM900, LOW);
  powerUpOrDown();
  Serial.begin(115200);
  Serial.print("Testing TinyGPS library v. ");
  Serial.println(TinyGPS::library_version());
  Serial.println("");
  Serial.println();
  Serial.println("Stats HDOP Latitude  Longitude  Fix  Date       Time     Date Alt    Course Speed Card  Distance Course Card  Chars Sentences Checksum");
  Serial.println("          (deg)     (deg)      Age                      Age  (m)    --- from GPS ----  ---- to London  ----  RX    RX        Fail");
  Serial.println("-------------------------------------------------------------------------------------------------------------------------------------");
  ss.begin(9600);
}

void loop() {
  bool newData = false;
  for (unsigned long start = millis(); millis() - start < 1000;) {
    while (ss.available()) {
      char c = ss.read();
      //Serial.write(c);  /*uncomment this line if you want to see GPS data*/
      if (gps.encode(c)) newData = true;
    }
  }

  if (newData) {
    float flat, flon;
    unsigned long age, date, time, chars = 0;
    unsigned short sentences = 0, failed = 0;
    static const double LONDON_LAT = 51.508131, LONDON_LON = -0.128002;
    print_int(gps.satellites(), TinyGPS::GPS_INVALID_SATELLITES, 5);
    print_int(gps.hdop(), TinyGPS::GPS_INVALID_HDOP, 5);
    gps.f_get_position(&flat, &flon, &age);  /*latitude, longitude, age*/
    print_float(flat, TinyGPS::GPS_INVALID_F_ANGLE, 10, 6);  /*print lat */
    print_float(flon, TinyGPS::GPS_INVALID_F_ANGLE, 11, 6);  /*print long */
    print_int(age, TinyGPS::GPS_INVALID_AGE, 5);
    print_date(gps); /* print date */
    print_float(gps.f_altitude(), TinyGPS::GPS_INVALID_F_ALTITUDE, 7, 2); /* print altitude */
    print_float(gps.f_course(), TinyGPS::GPS_INVALID_F_ANGLE, 7, 2);
    print_float(gps.f_speed_kmph(), TinyGPS::GPS_INVALID_F_SPEED, 6, 2);
    print_str(gps.f_course() == TinyGPS::GPS_INVALID_F_ANGLE ? "*** " :
   TinyGPS::cardinal(gps.f_course()), 6);
    print_int(flat == TinyGPS::GPS_INVALID_F_ANGLE ? 0xFFFFFFFF : (unsigned long)TinyGPS::distance_between(flat, flon, LONDON_LAT, LONDON_LON) / 1000, 0xFFFFFFFF, 9);
    print_float(flat == TinyGPS::GPS_INVALID_F_ANGLE ?
   TinyGPS::GPS_INVALID_F_ANGLE : TinyGPS::course_to(flat, flon, LONDON_LAT, LONDON_LON), TinyGPS::GPS_INVALID_F_ANGLE, 7, 2);
    print_str(flat == TinyGPS::GPS_INVALID_F_ANGLE ? "*** " :
   TinyGPS::cardinal(TinyGPS::course_to(flat, flon, LONDON_LAT, LONDON_LON)), 6);
    gps.stats(&chars, &sentences, &failed);
    print_int(chars, 0xFFFFFFFF, 6);
    print_int(sentences, 0xFFFFFFFF, 10);
    print_int(failed, 0xFFFFFFFF, 9);
    Serial.println();
    smartdelay(3000);
    if ((flat != previousFlat) || (flon != previousFlon)) {
      previousFlat = flat;
      previousFlon = flon;
      SendSQL();  //Function to send the coordinates
    }
  }
}

static void smartdelay(unsigned long ms) {
  unsigned long start = millis();
  do {
    while (ss.available()) gps.encode(ss.read());
  } while (millis() - start < ms);
}

static void print_float(float val, float invalid, int len, int prec) {
  if (val == invalid) {
    while (len-- > 1) Serial.print('*');
    Serial.print(' ');
  } else {
    Serial.print(val, prec);
    int vi = abs((int)val);
    int flen = prec + (val < 0.0 ? 2 : 1); // . and -
    flen += vi >= 1000 ? 4 : vi >= 100 ? 3 : vi >= 10 ? 2 : 1;
    for (int i=flen; i<len; ++i) Serial.print(' ');
  }
  smartdelay(0);
}

static void print_int(unsigned long val, unsigned long invalid, int len) {
  char sz[32];
  if (val == invalid) strcpy(sz, "*******");
  else sprintf(sz, "%ld", val);
  sz[len] = 0;
  for (int i=strlen(sz); i<len; ++i) sz[i] = ' ';
  if (len > 0) sz[len-1] = ' ';
  Serial.print(sz);
  smartdelay(0);
}

static void print_date(TinyGPS &gps) {
  int year;
  byte month, day, hour, minute, second, hundredths;
  unsigned long age;
  gps.crack_datetime(&year, &month, &day, &hour, &minute, &second, &hundredths, &age);
  if (age == TinyGPS::GPS_INVALID_AGE) Serial.print("********** ******** ");
  else {
    char sz[32];
    sprintf(sz, "%02d/%02d/%02d %02d:%02d:%02d ", month, day, year, hour, minute, second);
    Serial.print(sz);
  }
  print_int(age, TinyGPS::GPS_INVALID_AGE, 5);
  smartdelay(0);
}

static void print_str(const char *str, int len) {
  int slen = strlen(str);
  for (int i=0; i<len; ++i) Serial.print(i<slen ? str[i] : ' ');
  smartdelay(0);
}

void powerUpOrDown() {
  digitalWrite(pinPowerSIM900, HIGH);
  delay(2000);
  digitalWrite(pinPowerSIM900, LOW);
  delay(3000);
}

void SendSQL() {
  Serial.println("Start Send");
  gsm.SimpleWriteln("AT+SAPBR=3,1,\"Contype\",\"GPRS\"");
  delay(500);
  gsm.SimpleWriteln("AT+SAPBR=3,1,\"APN\",\"my.apn.com\"");   //APN
  delay(500);
  gsm.SimpleWriteln("AT+SAPBR=1,1");
  delay(3000);
  gsm.SimpleWriteln("AT+SAPBR=2,1");
  delay(3000);
  gsm.SimpleWriteln("AT+HTTPINIT");
  delay(500);
  gsm.SimpleWriteln("AT+HTTPPARA=\"CID\",1 ");
  delay(500);
  gsm.SimpleWriteln("AT+HTTPPARA=\"URL\",\"http://crbphil-001-site1.1tempurl.com/adddata.php\""); //URL
  delay(500);
  gsm.SimpleWriteln("AT+HTTPPARA=\"CONTENT\",\"application/x-www-form-urlencoded\"");
  delay(500);
  gsm.SimpleWriteln("AT+HTTPDATA=38,10000");
  delay(500);
  gsm.SimpleWriteln("addlati=");
  Serial.print(previousFlat, 6);
  gsm.SimpleWriteln("&addlongti=");
  Serial.print(previousFlon, 6);
  gsm.SimpleWriteln("\"");
  delay(3000);
  gsm.SimpleWriteln("AT+HTTPACTION=1");
  delay(15000);
  gsm.SimpleWriteln("AT+HTTPTERM");
  delay(500);
  gsm.SimpleWriteln("AT+SAPBR=0,1");
  delay(500);
  Serial.println("Finish");
}

And this is my PHP script to save data in the MySQL database:
adddata.php:
<?php
//Connect to MySQL
include("config.php");

// Perform a query, check for error
if (!mysqli_query($connect,"INSERT INTO track (tr_date, tr_time, latitude, longitude) VALUES ('".$_POST["addday"]."','".$_POST["addhour"]."','".$_POST["addlati"]."','".$_POST["addlongti"]."')")) {
  echo("Error description: " . mysqli_error($connect));
}
?>

What is the response from the gsm module after each AT command? The responses should give a clue to what is happening.

@MikaelFalkvidd there is no response. Just the set of commands in the serial monitor

Can you see a slight discrepancy in these lines?
gsm.SimpleWriteln("addlati=");
Serial.print(previousFlat, 6);
gsm.SimpleWriteln("&addlongti=");
Serial.print(previousFlon, 6);

I can.

I tried to fix that discrepancy but nothing happens, I mean there's no error or something.


text:
How to flash/blink I2C LCD backlight without delay function?
Since I am an using I2C LCD backpack, I'm unable to call in for pinmode to set variables like #define BACKLIGHT_PIN 13. I know lcd.setBacklight(HIGH); and lcd.setBacklight(LOW); controls the I2C LCD backlight, but if I use delay in the loop it slows down the whole loop.
How do I flicker the LCD backlight without using delay? I tried for example to blink without delay, but I don't know how to assign a global variable to lcd.setbacklight so as to control it.
I want to use an if statement to warn the user that so and so has happened, eg:
#include <Ticker.h>
#include <LiquidCrystal_I2C.h>
LiquidCrystal_I2C lcd(0x3F, 2, 1, 0, 4, 5, 6, 7, 3, POSITIVE);

//Ticker flashBacklight(toggleBacklight, 100);
// when I use ticker here am getting not declared in scope
const int buttonPin = 3;
int buttonState = 0;
// pls declare flashBacklight, long flashBacklight = 100; ??
// pls declare toggleBacklight

void toggleBacklight() {
  // lcd.setBacklight(!lcd.getBacklight());
  // !lcd.getbacklight() spelling mistake ? or it is setbacklight?
}

void setup() {
  lcd.begin(20, 4);
  lcd.setBacklight(HIGH);
  pinMode(buttonPin, INPUT);
 }

void loop() {
  buttonState = digitalRead(buttonPin);
  if (buttonState == HIGH) {
    // if button goes high the back light must keep on flashing until it's released
    flashBacklight.start();
    //flash the lcd backlight
  } else {
    flashBacklight.stop(); // Stop flashing the backlight
  }
  flashBlacklight.update();
}

But delay slows down the whole loop, so how do I flash the backlight without it? Thank you.

Besides the standard 'compute a target millis() and compare' standard, which can get clunky when you have to handle more than 1 repeating or delayed event, there are also more than one decent library that abstract the concept, but also add features.
One example is the Ticker library.
With these methods, you create a callback function and pass that function name into the object constructor, along with the timing parameters.
So you might:
[various #include, #define, etc.]

Ticker flashBacklight(toggleBacklight, 100); //call toggleBacklight() every 100ms

// Create the callback function, which just toggles the backlight each call.
void toggleBacklight() {
  lcd.setBacklight( !lcd.getBacklight() );
}

setup() {
  [...]
}

loop() {
  // Start or stop the ticker based on your own situation. Once started, it will call your callback function at the specified interval until stopped.

  if (warningSituation) {
    flashBacklight.start();
  } else {
    flashBacklight.stop();
  }

  flashBlacklight.update();
}

Another related library is SimpleTimer
EDIT
Your code example, updated:
#include <Ticker.h>
#include <LiquidCrystal_I2C.h>
LiquidCrystal_I2C lcd(0x3F, 2, 1, 0, 4, 5, 6, 7, 3, POSITIVE);

void toggleBacklight();

Ticker flashBacklight(toggleBacklight, 100); //when i use ticker here am getting not declared in scope

const int buttonPin = 3;
int buttonState = 0;
                      // pls declare   flashBacklight   , long flashBacklight = 100;   ??
                      //   pls declare toggleBacklight

void toggleBacklight() {
 // lcd.setBacklight( !lcd.getBacklight() );  // !lcd.getbacklight() spelling mistake ? or it is setbacklight?
}
void setup() {
   lcd.begin(20, 4);
 lcd.setBacklight(HIGH);
 pinMode(buttonPin, INPUT);
 }
void loop() {
      buttonState = digitalRead(buttonPin);
   if (buttonState == HIGH)          // if button goes high the back light must keep on flashing untill its released
   {
    flashBacklight.start();          //flash the lcd backlight
  } else {
    flashBacklight.stop();           // Stop flashing the backligh
 }
   flashBacklight.update();
  }

can you show me a example of flashing with button press example ? am getting compiler error "not declared in the scope " so if u can show me   its complete usage it would be easy for me to learn , i want to put the code here,but if i do it exceed character left, how to put the code here?

I linked to the Ticker library -- it has an example of how to use it. If you are using Arduino IDE, you will need to install the library, and #include it's header file. If you want to put a big block of code in, you can edit your original question, I believe.

oh.. ty library and all those installed correct,problem is global variable declaration..pls check the original question and pls help fill the gaps ..ty

Yes sir, its global variable declaration.. pls see the above update code...

You should move the flashBacklight function definition to before the Ticker Use. I will update my example soon. I don’t know which LCD library you are using. At least one has getBacklight(), but if yours doesn’t, you can keep track in another global.

am using lcd library by  F. Malpartida , and yes i think it dosent have getBackligh() , i had preveiously   "class LiquidCrystal_I2C' has no member named 'getBacklight'" compiler error...

You will need to alter the pin / bit tied to the backlight led.
To do that you will need to be able to read the state of all the pins on the i2c expander.
That can be done by reading back the pin state from the i2c expander or to hold the pin state in a buffer.
Once you know the pin state, you can OR or NEG it to clear or set the pin.

well, this is easy method reading the state of A and k On the lcd pin, but wish to learn by using i2c and also saves digital pin, as of now every pins on my uno is used and nothing to spare :( ....

" nothing to spare" - in that case, the answer is simple. you essentially want to change the state of a pin without having a pin connected to it.

with that said, you can re-use one of the lcd pins, recognizing that those pins' state is only used when the state of the EN pin is going through a state change. So any other times, you can change the other pines freely without messing up the lcd display.

ok ok, i under stood your point, for instance i define  #define BACKLIGHT_PIN 2 when warning triggers pin A goes high and low , if i keep the pin A which is connected to digital pin 2 and digital write (2,high) and Low i can control its backlight, this way i must keep the pin connected always right? now from i2c point of view, lcd.setBacklight(HIGH);  sets backlight high, how do i declare lcd.setBacklight(HIGH);  to global variable and control it?

You record the timestamp when you want the LED to turn off again and then check that against millis in the loop()
  if ( level 1 > level 0)
  {

     NewTone(4,1000,50); // initiate alarm
     blinking = true;
     lcd.setBacklight(HIGH);
     lcdToggleTime = millis();// this is a global
     lcdOn = true;
  }else {
     blinking = false;
     lcd.setBacklight(LOW);
  }

  //at the start or end of loop(); make sure it's always checked.
if(blinking){
      if(millis() - lcdToggleTime>+100) {
         if(lcdOn)
             lcd.setBacklight(LOW);
         else
             lcd.setBacklight(HIGH);
         lcdOn = !lcdOn;
         lcdToggleTime = millis();// this is a global
     }
}

The background should turn on and off and on and off... just like the blink-without-delay example. When a value is added to millis(), then the rollover problem is introduced. See the blink-without-delay how to use millis(): https://www.arduino.cc/en/Tutorial/BlinkWithoutDelay

@jot fixed the code

if (millis() > lcdToggleTime) will not work properly across a
millis() rollover. The “Blink without delay” tutorial uses the idiom
if (millis() - lcdLastToggle > 100), which is rollover-safe.


text:
How do I connect an Adafruit headphone jack to an Arduino 101?
I just purchased Adafruit headphone jack and I want to know how to connect it to an Arduino 101. I'm trying to use a breadboard to play a sample tone melody from the Arduino libraries, which I want to hear with my iPhone headphones.
I have been looking online for instructions on how to do this, but found nothing. Please advise.
Thank you!

You mean this thing? https://www.adafruit.com/product/1699

Yes that thing! :)

First you need to confirm that the socket will actually work with your headphones. Make sure that the ground connection of the headphones (either the sleeve or the ring right next to the sleeve, depending on the type of headphones) is serviced by a connection.
Second you need to wire one or both of the tip and the first ring to the Arduino's output that you are using to generate audio. This should be done through a capacitor to block the DC voltage and only pass the AC waveform.

simulate this circuit – Schematic created using CircuitLab
Ideally, though, you should first pass the signal through a small headphone amplifier otherwise you risk drawing too much current out of the Arduino's GPIO pin.


text:
Can you use an input pin instead of ground in Arduino circuitry?

Beginner here: Would the circuit in the picture work or do input pins not absorb the energy as ground does? I know setting the pin as an input makes the direct 5V connection safe but maybe I'm mistaken. I'm trying to understand the nature of how these connections are made. Thank you in advance!

An input pin can only sense the voltage that is applied to it - whether it is above or below a pair of thresholds.
In your existing circuit when the button is not pressed the voltage sensed by the pin is 0V because it is connected to 0V (also known as Ground) through the resistor. When you press the button the input pin is connected directly to +5V, so the pin senses 5V.
If you remove the resistor or the connection to ground the pin can still sense 5V on it when the button connects it to 5V, but when you release the button the input pin then isn't connected to anything at all. It's not connected to 0V, so it can't sense what voltage is there - there simply isn't any voltage connected to it (no voltage isn't the same as 0V).
In this case the pin is said to be "floating". It's neither HIGH (5V) nor LOW (0V), it's just dangling around not knowing what it's doing.
If you want to get more technical and look at the mechanics of it, it's helpful to know that the gate of a MOSFET (which is what the input pin actually is) looks to all intents and purposes like a small capacitor.  When you connect the input pin to +5V the capacitor is charged up (current flows into it from 5V to charge it). When you connect the input pin to 0V it discharges (current flows out of the capacitor down to 0V). When charged you have a HIGH and when discharged you have a LOW.
However when a charged capacitor has no connection it (for a certain amount of time, due to self discharge) keeps hold of its charge. So if you charge it with +5V and then disconnect it you will still get +5V on the capacitor. That is until it discharges through internal leakage currents.
Those leakage currents though are so small and the capacitor is so sensitive that the input pin acts like a radio antenna. It picks up noise from the surrounding area (electromagnetic waves) which can charge and discharge the capacitor pretty much at random. So at times you may see the input as HIGH and at other times as LOW, purely depending on chance. And the longer your wires the more noise it will pick up.
The worst source of noise is the 50/60Hz mains hum that is all around you. You can see this in reality if you graph the voltage on a disconnected ADC pin and bring your hand close to it - you act like a capacitively coupled antenna and you can see the mains waveform on your graph.
It's the same on a digital input pin, except that it converts it to a square wave as it passes the thresholds (you might like to look at schmitt triggers for more detail about how it does that).
So adding the pull down (or pull up if you prefer) resistor is critical to making the input pin see what you want it to see, and not just random noise.
Since the input is like a capacitor selecting the right value of resistor can be quite important in some situations. For a simple button like this there's nothing to worry about, but for something like a rotary encoder where the input signal may change more rapidly the resistor value does become more of a concern.  Have too high a value and the gate will take too long to discharge (or charge if it's a pull up resistor). Too low and too much current could be wasted through the resistor when the button (or encoder) is active (potentially damaging the button if it's a low current sensitive device).

If you remove the ground wire, digital pin 2 will be left "floating" until the button is pressed, and this is not a good thing to do:
https://electronics.stackexchange.com/questions/83133/arduino-digitalread-reading-wrong
There is a way to eliminate the pull-down resistor and simplify the wiring by using pinMode(BUTTON_PIN, INPUT_PULLUP); in setup(). You would connect one "leg" of the N.O. momentary push button switch to ground and the other "leg" to Pin 2. You will still need to "debounce" the switch, and for that I recommend a library.
There is a link to a good library here: https://playground.arduino.cc/Code/Bounce.
The example sketch called bounce.ino is a good place to start.


text:
Two LED Patterns Task Controlled by GUI
I am very new to Arduino and coding/programing. I set a task for myself to make a simple circuit of 5 LEDs controlled by pins 2, 4, 8, 11, 12. I want to be able to make two different pattern for the LEDs and be able to turn each pattern on or off with buttons in python. I was able to achieve this using millis and several if statements. I have one problem with the code I created and one question.
The problem:
When I run my upload my code and press the buttons on my python gui only one task can run at a time. I would like to be able to run both at the same time if I press both run buttons. I have spent hours trying to find where my code is blocking this from being possible. Any advice on how to solve this problem would be greatly appreciated.
The question:
During my research I stumbled across the possibility of using switch / case commands in stead of several if statements. I tried several times to get this to work but am not wise enough to get it to work. Any tips of how to make this work would be greatly appreciated.
Arduino code:
char serialData;

const int blue1 = 12;
const int blue3 = 8;
const int red1 = 4;
const int red2 = 2;

int blue1state = LOW;
int blue3state = LOW;
int red1state = LOW;
int red2state = LOW;

unsigned long previousMillis1 = 0;
unsigned long previousMillis2 = 0;

const long interval1 = 0;
const long interval2 = 2000;
const long interval3 = 4000;
const long interval4 = 3000;
const long interval5 = 6000;
const long interval6 = 9000;

void setup() {
  Serial.begin(9600);
  pinMode(blue1, OUTPUT);
  pinMode(11, OUTPUT);
  pinMode(blue3, OUTPUT);
  pinMode(red1, OUTPUT);
  pinMode(red2, OUTPUT);
}

void loop() {
  unsigned long currentMillis = millis();

  //TASK ONE
  if (Serial.available() > 0) {
    serialData = Serial.read();
    Serial.print(serialData);
  }

  if (serialData == '1') {
    if (currentMillis - previousMillis1 >= interval1) {
      red1state = HIGH;
    }

    if (currentMillis - previousMillis1 >= interval2) {
      red1state = LOW;
      red2state = HIGH;
    }

    if (currentMillis - previousMillis1 >= interval3) {
      red2state = LOW;
      previousMillis1 = currentMillis;
    }
  }

  if (serialData == '3') {
    red1state = LOW;
    red2state = LOW;
  }

  //TASKTWO
  if (serialData == '2') {
    digitalWrite(11, HIGH);

    if (currentMillis - previousMillis2 >= interval1) {
      blue3state = HIGH;
    }

    if (currentMillis - previousMillis2 >= interval4) {
      blue3state = LOW;
    }

    if (currentMillis - previousMillis2 >= interval5) {
      blue1state = HIGH;
    }

    if (currentMillis - previousMillis2 >= interval6) {
      blue1state = LOW;
      previousMillis2 = currentMillis;
    }
  } else if (serialData == '4') {
    blue1state = LOW;
    blue3state = LOW;
    digitalWrite(11, LOW);
  }

  digitalWrite(blue1, blue1state);
  digitalWrite(blue3, blue3state);
  digitalWrite(red1, red1state);
  digitalWrite(red2, red2state);
}

Python code:
import tkinter as tk
import serial
import time

arduinoData = serial.Serial('COM3',baudrate = 9600, timeout=1)
def task_one():
    arduinoData.write(b'1')
def task_two():
    arduinoData.write(b'2')
def off_one():
    arduinoData.write(b'3')
def off_two():
    arduinoData.write(b'4')

HEIGHT=700
WIDTH=800

LED_Control_Window = tk.Tk()

canvas = tk.Canvas(LED_Control_Window, height=HEIGHT, width=WIDTH)
canvas.pack()

frame = tk.Frame(LED_Control_Window, bg='#80c1ff')
frame.place(relx=0.1, rely=0.1, relwidth=0.8, relheight=0.8)

label = tk.Label(frame, text='LED Flash Patterns', bg='#beced4')
label.place(relx=0.34, rely=0.0, relwidth= 0.35, relheight=0.1)

button = tk.Button(frame, text="Task One", bg='#50bd57', command=task_one)
button.place(relx=.15, rely=0.25, relwidth= 0.25, relheight=0.15)

button = tk.Button(frame, text="Task Two", bg='#afbd3d', command=task_two)
button.place(relx=0.62, rely=0.25, relwidth= 0.25, relheight=0.15)

button = tk.Button(frame, text="Stop Task One", bg='#f03535', command=off_one)
button.place(relx=0.15, rely=0.6, relwidth= 0.25, relheight=0.15)

button = tk.Button(frame, text="Stop Task Two", bg='#f03535', command=off_two)
button.place(relx=0.62, rely=0.6, relwidth= 0.25, relheight=0.15)

LED_Control_Window.mainloop()

Can you have a look with PuTTY or something like that to see what the Python code is sending on COM3 when you press two buttons at the same time?

I will give that a shot to see. What happens now when I press the first button the pattern will begin. Then when I press the second button the first pattern pauses and the second one begins. Thank you for the tip!

you have a logic error in your code .... interval1 code always runs when interval1 passes ... then interval1 and interval2 both run ... etc. etc. .... reverse the order of if statements and use else if ... that way you check if interval3 passed .... if it did not, then check interval2 ... and so on ..... switch/case is same as a sequence of else if statements

use if (serialData == '1')  task1 = true; ... then run TASK ONE  if task1 is true ... if (task1) { .... make task1 false at the end of TASK ONE ... do similar for TASK TWO

Thank you both ocrdu and @jsotola for the tips I will comment my updated code when I finish it.

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


text:
Voltage, current measurement from solar panel using INA219 and ESP-12F
I recently started tinkering with ESP-12F thus I am a novice here. As a standard novice project, I am making a standalone weather station for my living room. I want to use solar panels to charge the batteries which power up the ESP-12F via USB. I am using ESP-12F as a controller and sending data to Rpi using MQTT.
I am using the following items:

ESP-12 F powered by USB
2.5W 5V solar panel ( I want to connected two in parallel but for now using only one )
RPi 3B
INA219A to measure voltage and current generated by solar panel.
IN4001 diode as blocking
DHT11 sensor for temp and humidity values
Battery pack to charge 2 x 2500mAh batteries ( This is not done yet )

I am quite confused by the connections to INA219 and the data its providing. Thus, ESP-12F is still connected to independent usb power source and my goal is for now to understand and monitor the voltage and current generated by solar panel.
The INA219 Vcc, GND, SDA, SCL are connected to ESP-12F. I can read the values and observe them on serial monitor or mqtt panel.
1. Below is the breadboard connection when INA219 Vin+ is NOT connected.

The voltage measurement sent via MQTT is as below:
Ignore graph, I was pluging in/out Vin wire too many times thus very bizzare lines.

Current connections are as below:
Solar Panel (-) --> INA219 Vin (-) and breadboard to power LED
Solar Panel (+) --> Only to breadboard to power LED [INA219 Vin+ NOT connected]
ESP-12F 3V --> INA219 Vcc
ESP-12F GND --> INA219 GND
ESP-12F D1 --> INA219 SCL
ESP-12F D2 --> INA219 SDA
ESP-12F is powered by separated USB power source
Code using which the values are computed:
I have used Adafruit_INA219 library.
  shuntvoltage = ina219.getShuntVoltage_mV();
  busvoltage = ina219.getBusVoltage_V();
  current_mA = ina219.getCurrent_mA();
  power_mW = ina219.getPower_mW();
  loadvoltage = busvoltage + (shuntvoltage / 1000);

I dont understand the values sent by INA219 and have no idea how to interpret them. At this point, INA219 is connected to ESP-12F 3V power (Vcc) and GND. It does not have any Vin. Why there is a load voltage of -1.9 and current?
2. When INA219 has Vin(+) and Vin(-) connected

When I connect the Vin+ and Vin- of INA219 I dont have any voltage/current on the breadboard. You can see the LED if OFF. I dont understand why this happens. The whole circuit on breadboard is redundant once I connect INA219 Vin pins to solar panel output pins.
Current connections are as below:
Solar Panel (-) --> INA219 Vin (-) and breadboard to power LED
Solar Panel (+) --> INA219 Vin(+) and breadboard to power LED
ESP-12F 3V --> INA219 Vcc
ESP-12F GND --> INA219 GND
ESP-12F D1 --> INA219 SCL
ESP-12F D2 --> INA219 SDA
ESP-12F is powered by separated USB power source
The voltage and current values at this point is shown below:

The load voltage increases and the difference which is approx 2.1V.
This delta voltage matches the voltage values from solar panel when measured by multimeter at this point. Thus, I would assume load voltage = current voltage generated by solar panel. But, current is unchanged and LED on breadboard if OFF the moment I connect INA219 Vin. Thus, I assume I have done wrong connections.
It will be great if you can point out my mistakes and make suggestions!
Thank you!

You had a long post, but yet missing a lot of critical information for diagnosis. It will be better to provide a schematic than the breadboard picture, as it doesn't even show the IN219 on it. Where is your current shunt? and do you have the pull-up resistors for the I2C? does your I2C works? simply your post and focus on one question that you want to ask or the thing that you need help.

Vshunt = Vin+ - Vin- and typically < 50mV or just a few mV, Vbus = Vin - GND and therefore should be around 5V in your case, Load Voltage should be very close to VBus. So all your data doesn't make any sense. For the current, the value return is integer for mA, so it need to divided by 1000. So it is better to show your schematic/connection diagram and your Arduino sketch.

You connected the V- and V+ probes of the INA module direct to the V- and V+ of the solar panel. That means you connect V+ with V- from solar panel  over a 0.1 Ohm resistor. That is like a short. The Solar panel gets overloaded and the voltage breaks down. Lucky you, the solar panel can not provide more current. If it could, then the shunt resistor would be grilled. RIP ;-). Try put the v+ and V- in series with the LED and LED_Resistor. e.g.
Solar+ --> IN4001 --> INA+ |no connection| INA- --> LED --> R(LED) --> Solar-

That would make more sense. It'll show you how much current is drawn by the LED.
If you want to know how much current the panel can deliver, you would have to build a circuit with a potentiometer and measure the Voltage between V+ and V- of the Panel. You can also use the INA to mesasure the current through the potentiometer. Begin with a high resistancy, then turn the poti towards lower resistance and check when the voltage breaks down. The INA shows you the current. But be aware that, the max current depent on the amount of light the panel is exposed to and on the age of the panel itselves. So the values will change as these conditions change.


text:
If condition for switch not working as expected
I am trying to write a simple program to control one LED with two switches.
If any of the switches is pressed, I want to turn the LED on.
My LED however is always ON even when none of the switches are pushed.
Why could this happen?
Thanks!
https://www.tinkercad.com/things/7SRoEXkHRqh-one-led-two-switches-

the input pins are directly connected to 5V, as the button has the pins on the sides directly connected (the real button sits between right and left). move the two red wires at the top, which go to the input pins, to the right side of the switches (above where the resistors are connected). If that works, I will write an answer

Now, that you changed the circuit, it seems to work. Is that correct?

It's easy to confuse the pins of these single-pole buttons - I still do it. Only two pins are needed for this kind of button. The extra two are there for mechanical stability on the PC board.
Lay the button on one of its sides:

If the two upper pins come out of the top edge, those pins are switched - either open, or shorted by the button. Ditto, for the two bottom pins.

If instead, the two upper pins come out of opposite edges, those two are literally a single piece of wire passing through the button-frame and so are always shorted to each other. These two pins together are open with respect to the bottom two pins when the button is released, or shorted to the bottom two pins when the button is pressed.

Update:

I probably won't remember your info next time I need to use one of
these switches, so I'll still have to just test it... :(

Thanks, @Duncan C. I probably made it more complicated than it needed to be! How about:
Each pair of pins is a flat metal strip, bent to pass through the switch body, each end of it pointing down at the PC board; roughly into the shape of the letter 'C'. Looking at one of the pins, there is only one other pin that could be its other end, because you can only  bend a flat strip toward one of its faces, not edgewise.

That's useful information on how to figure out which pins are switched and which are connected. I just use a multimeter to figure it out. I probably won't remember your info next time I need to use one of these switches, so I'll still have to just test it... :(

It's hard to tell which pins of the switch do what. Since you have your inputs set up as INPUT (instead of INPUT_PULLUP) you should have a resistor (10k Ω, say) tying those pins to ground. Then the other end of switch should connect to +5V. Don't connect the switches to both +5V and ground.
Use a multimeter on continuity to make sure that the pins of the switch that you are using are open normally, and close when you press the switch. With 4 pins it's easy to get confused as to which switch pin does what.


text:
Maximum baud rate for sending a byte of data via SoftwareSerial from master Arduino UNO to slave Arduino UNO
I am trying to read data from a Blynk widget via ESP8266 and Arduino UNO and trying to send it to another slave Arduino UNO.  But, the problem is the data is taking some time to reach to the slave Arduino for further processing and I need it to be fast as it is needed for controlling a drone.
If any one can help, please help. I am a tenth grader and a newbie. So, I don't have a lot of experience.
Here is the code for the master Arduino:
#include <ESP8266_Lib.h>
#include <BlynkSimpleShieldEsp8266.h>
#include <SoftwareSerial.h>   //We are using software serial so as not to conflict with serial download and monitor

SoftwareSerial mySerial(5,6); // RX, TX

int of=0;
int throttle=0;

// You should get Auth Token in the Blynk App.
// Go to the Project Settings (nut icon).
char auth[] = "auth";

// Your WiFi credentials.
// Set password to "" for open networks.
char ssid[] = "wifi_name";
char pass[] = "wifi_pass";

// Hardware Serial on Mega, Leonardo, Micro...
//#define EspSerial Serial1
// or Software Serial on Uno, Nano...
//#include <SoftwareSerial.h>
//SoftwareSerial EspSerial(2, 3); // RX, TX

// Your ESP8266 baud rate:
#define ESP8266_BAUD 115200

ESP8266 wifi(&Serial);
WidgetLED l(V3);

void setup()
{
 // Debug console
 Serial.begin(9600);
 delay(10);
 // Set ESP8266 baud rate
 Serial.begin(ESP8266_BAUD);
 delay(10);
 Blynk.begin(auth, wifi, ssid, pass);
 mySerial.begin(9600);
}

void loop()
{
 Blynk.run();
 l.on();
 mySerial.write(of);
 mySerial.write(throttle);
}

BLYNK_WRITE(V1)
{
  of = 100+param.asInt();
}

BLYNK_WRITE(V2)
{
  throttle = param.asInt();
}

how do you know that the bottleneck is the baud rate? ... the slave code could easily be running slow

If the distance (wires) between the 2 processors is short enough, you might consider I2C or SPI.  Also, for speed you should make sure you are using all the hardware support available and not emulating serial ports using software.  If there are not enough hardware resources on the processors used on the Arduino boards you picked out - consider using a more capable processor on a different Arduino board.

A practical answer to the maximum baud of SoftwareSerial is non-trivial and probably not as helpful to you as you might expect in solving the fundamental problem of getting information from Blynk through to whatever in your project actually needs that information timely.  Typically in aerial (I presume) drone applications, people are concerned about weight as well.  So, I'm curious: are all three of these things going to be mounted on the drone?  (Why) do you need all three?

Yes all three are mounted on the drone...  but i have quite powerful motors and 10*4.5 blades @timemage

@jsotola yeah that was the problem....thank you for ur help but now there is another problem it is tipping over   :)

@st2000 i could not use spi because i could not understand how it works.... and i2c i did not use because already my arduino is communicating with the bmp via i2c i dont know if it supports two wires(Wire.h)....

I2C supports more than two devices on the same bus (same Wire instance) such that having multiple buses is often unnecessary.  The case is similar with SPI except that multiple select lines are typically needed. When using an UNO as a slave, you may find I2C easier because it has a built-in flow control mechanism (clock stretching).


text:
Arduino Master SPI MISO Receive Data
I'm trying to interface an Arduino Mega with an AD7714 ADC. This ADC requires a command to be sent to the communications register (in my case 0x5C) in order to begin a read from the data register.
My question is how do I receive the data that is transmitted from the Slave ADC to the Master Arduino on the MISO line?
At the moment I have this code in an interrupt that is activated when the DRDY goes low:
byte dataIn;
byte dataOut = 0;
adc_write_reg(0x5C); //tell ADC to read data from data register
dataIn = SPI.transfer(dataOut); //transmit data in order to recieve data??

Thanks!

It seems like your more wondering the what and why of the sent data when your goal is to receive data.  Is that the case?

I'm not sure what you mean by the what and why :/ Simply put all I need to do is store the data recieved on the MISO line in a variable

Typically you need to do two SPI transactions, one for Writing data by setting the R/W bit of the Comm register to Write, and write the data with SPI.transfer(), close the transaction, then re-establish a SPI transition and set the Comm register with R/W bit as Read, and read in the data with another SPI.transfer(). BTW, don't do I/O data access within your Interrupt function. Keep your Interrupt function as short as possible by just set/reset a status...

The write is to send the command, the read is to get the data. Here is a library that I'm familiar for another ADI chip with similar mechanism that you could take a look on how the code looks like.

Sending 0x5c is just to tell the chip you want to read the data register. You can ignore the this first received byte. You then send two or three zero bytes (0x00), to get your 16-bit or 24-bit ADC result.


text:
Arduino interrupt for serial data on digital pin, that is too large for the serial buffer
I am using an Arduino Nano in combination with a NEO 6m GPS module. The GPS module is sending data, consisting of a few hundred chars, every second. Since I am communicating with my PC over the integrated serial RX and TX pins of the Arduino, I cannot use them for the sensor without being able to display anything sent from the Arduino on my PC. I am using the SoftwareSerial library to mark two digital pins as my new RX and TX to communicate with the GPS sensor.
The problem is that I have to actively listen to the RX pin at the moment the data is incoming, because otherwise data will be lost, since it's too much to be placed into the serial buffer completely. But on the other hand: I don't want to actively wait for the digital pin to receive data, so I would be in time to read it. It would be best handled with an interrupt every time the digital RX pin starts to receive data. But I read that SoftwareSerial is not compatible with this kind of interrupt, since it has a built-in interrupt itself everytime new data arrives to save it onto the buffer.
This is what I have tried:
#include <SoftwareSerial.h>

// The serial connection to the GPS module
SoftwareSerial ss(4, 3);
String serialString;

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

  //Interrupts when a transmission begin in the RX-Pin is recognized
  attachInterrupt(digitalPinToInterrupt(4), readGpsSerialData, CHANGE);
}

void loop() {
  //processing data that takes too long to check frequently enough if data is being transmitted at the moment
  Serial.println("In Loop");
  delay(1000);
}

//Read all the incomming data once transmission started
void readGpsSerialData() {
  String serialString = "";
  while (ss.available() > 0) {
    char serialChar = ss.read();
    serialString += serialChar;
  }
  lastGpsString = serialString;
  Serial.print("Data from Interrupt: ");Serial.println(lastGpsString);
}

I think the problem is that my interrupt activates, not just once when the transmission starts, but every time the RX digital value changes (so a lot of times in the transmission). A data RDY value would be nice for this interrupt trigger but the GPS module does not have one.

I guess the delay in loop stands for some other complex code that takes long to execute? I would try to get to a non-blocking coding style, so that you can check for serial data with higher frequency. Without knowing what this complex code is, we cannot advice at that.

Or you could increase the buffer size by editing the SoftwareSerial library. Though I would argue, that this is not a good solution, since it makes your code less portable (you would need to use that modified library everywhere you want to compile the code)

Does it really take longer than 1 second to run your loop code?  Perhaps that should be optimized and then this wouldn't be a problem.

You can use the hardware serial port both for reading from the GPS and for writing to the PC. You will not be able to also read from the PC though.

Thanks, timemage - I'd busted an edit. Corrected here:   Following on to @EdgarBonet's suggestion, you could swap the roles of Serial and SoftwareSerial. Then you'd have one channel dedicated to the PC and the other, faster one, dedicated to the GPS. You'd still need to make your code non-blocking to prevent dropped characters on either channel, and you'd want to service each channel more frequently (just for collecting the input, not necessarily processing it), for the same reason.

@EdgarBonet Interesting aspect, but wouldn't this just cause the data to "pass-trough" from the Arduino RX pin to the USB port, basically bypassing the Arduino completely?

@PMF: No, the PC does not see the data coming to the Arduino's RX. It only sees what comes out of the Arduino's TX, i.e. what you Serial.print().

GPS is a really slow communication, it communicates in 9600bps and data only available once in every second. Any MCU running at much slower than an Arduino Uno running at 16MHz should be able to handle it, with a small rx buffer. If there is a problem, it is because of the user code implementation.
You didn't mention which Arduino board you are using. Arduino's implementation of attachInterrupt() function has quite limited digital pins that you could attach an interrupt to it. See the documentation. Even it can handle interrupt on pin4, the CHANGE means that it would be triggered in every single bit change, which is really unnecessary.
Secondly, there are a few "do and don't" for setting up an interrupt callback function, it all come down to "keep it short and simple", to have a while..loop and Serial print within an interrupt callback is one of those things that should be avoid, for that I suggest to read Nick Gammon's Interrupts.
There is a misunderstanding of "actively listen" of RX. The Serial.available() is a function that behave like an onEvent() callback internally, so it is non-block by simply doing a checking with if(Serial.available(), it will only blocking by putting it in a while loop. Furthermore, Serial.available() only turn from 0 to 1 when a full byte is received.
I'd suggest to not using interrupt, and make the following changes. This should provide plenty of time for handling other communication while receive GPS data stream.
#include <SoftwareSerial.h>

// The serial connection to the GPS module
SoftwareSerial ss(4, 3);

void setup() {
  Serial.begin(9600);   // change baudrate to 115200 to improve performance
  ss.begin(9600);
}

void loop() {
  String serialString = "";

  // this code block only execute when a character is fully received
  if (ss.available() > 0) {
    char serialChar = ss.read();
    serialString += serialChar;
    // only print the string when the `\n` is received (i.e. full GPS string)
    if (serialChar == '\n') {
      Serial.println(serialString);
    }
  }

  // there are plenty of time to handle the rest of the communication with the PC here
}

To avoid a buffer overflow, I would recommend increasing the communication speed on the PC side. You can easily set Serial.begin(115200); or even higher, as the comment in your code suggests. The PC and also the Arduino work just fine with that. That will make sure you can send out all the input from the GPS receiver much faster than new data comes in, so you shouldn't loose anything. Just make sure that you use the same value on the Arduino and the PC.

There are 2 aspects here.
The first is that the continuous flow of NMEA data is not THAT important. When you are ready to read, you can discard any pending input, ie flush the buffer, and start reading from the next $ onwards.
You can also limit the number of NMEA verbs displayed (there are commands to do that), so that less information is sent to Serial.
The second aspect is that most GPS modules send data at 9,600 bauds, which is quite slow, and every second (that's what the PPS pin is for). So you read data, store the lines in a buffer, and parse the buffer. Rinse and repeat. Even an Arduino Uno should be good enough. And as I said, if there's too much data, discard and start reading again.


text:
SIM A9G: +CME ERROR: 53 failure
I'm using a SIM A9G.  When I send HTTP GET command from the serial monitor, it responds. But, it doesn't work when included in the code.
#include <SoftwareSerial.h>
SoftwareSerial myserial(8, 7); // RX: 8, TX:7

void setup()
{
//  Wire.begin(I2C_SLAVE_ADDRESS);
  Serial.begin(19200);
  myserial.begin(19200);    // 9600, 19200, 38400, 57600, 74880, 115200

//  ET.begin(details(mydata), &Wire);
  Serial.println("JSON Initializing...");
  Serial.println("GPRS Starting..........");

//  myserial.listen();
  myserial.println("AT");
  delay(500);

  myserial.println("AT+CREG=?");     //Check Network regiistration, wait a while
  delay(1000);
  ShowSerialData();

  myserial.println("AT+CCID");  //Specify the connection type
  delay(1000);
  ShowSerialData();

  myserial.println("AT+CGATT=1");
  delay(2000);
  ShowSerialData();

  myserial.println("AT+CGDCONT=1,\"IP\",\"web.gprs.mtnnigeria.net\"");//Specify the APN
  delay(2000);
  ShowSerialData();

  delay(2000);
}

void loop()
{
  myserial.println("AT+CGATT=1");
  delay(2000);
  ShowSerialData();

  myserial.println("AT+CGACT=1,1");
  delay(2000);
  ShowSerialData();

  myserial.println("AT+HTTPGET=\"https://postman-echo.com/get?foo1=bar1&foo2=bar2\"");
  delay(5000);
  ShowSerialData();

  myserial.println("AT+CCLK?");
  delay(1000);
  ShowSerialData();

  delay(3000);
}

void ShowSerialData()
{
  while (myserial.available() != 0)
  {
    Serial.write(myserial.read());
    //delay(50);
  }
}

The output at the serial monitor is the following:
+CGATT:1

OK
AT+CGACT=1,1

OK
E⸮⸮T⸮OZ⸮y:/⸮͵*⸮⸮⸮m/⸮⸮⸮⸮⸮=bar1&foo2=bar2"

+CME ERROR: 53
failure, pelase check your network or certificate!

AT+CCLK?

+CCLK: "21/02/22,18:19:43+01"

OK

start with the Arduino software serial example sketch

A9G Module also support https request ...Due to some other reason , you are getting that error ... Bcz, i tried same server to get the data , is working fine ..

For me HTTPS working for first 7 or 8 times after that it fails.. @sumit chatterjee for you it works continuously?

You must use this sequence.
AT+CREG=?
AT+CCID
AT+CGATT=1
AT+CGDCONT=1,"IP","ba.amx"
AT+CGACT=1,1

Some explanation as to why might be helpful.

i can confirm that  it works. I tested with my Maduino that didn't connect to server and didn't send HTTP get request.


text:
How can I send 2 orders using nRF24L01
My project is to control a servo with a joystick using nRF24L01. I have this code working well, but the problem is that I want to add a lamp in the receiver side, and a switch in the transmitter side. I had tried so many codes from the internet, but nothing works. When I implement the code for the led, the servo and the joystick will stop working unfortunately.
Maybe the problem could be solved by transmitting on 2 channels each channel has a command.  But, the question is how this is the transmitter code that is working normally :
Transmitter Code
#include <SPI.h>
#include <nRF24L01.h>
#include <RF24.h>

RF24 radio(7, 8); // CE, CSN
const byte address[6] = "00001";

void setup() {

  radio.begin();
  radio.openWritingPipe(address); // 00002
  radio.setPALevel(RF24_PA_MIN);
  radio.stopListening();
}

void loop() {
delay(5);

 radio.stopListening();
  int potValue = analogRead(A0);
  int angleValue = map(potValue, 0, 1024, 0, 23.5);
 radio.write(&angleValue, sizeof(angleValue));

  delay(5);
  radio.startListening();

}

and this is the receiver code:
Receiver Code
#include <SPI.h>
#include <nRF24L01.h>
#include <RF24.h>
#include <Servo.h>

RF24 radio(7, 8); // CE, CSN
const byte address[6] = "00001";
boolean button_state = 0;

Servo myServo;

void setup() {

    Serial.begin(9600);
  myServo.attach(5);

  radio.begin();

  radio.openReadingPipe(0, address); // 00002
  radio.setPALevel(RF24_PA_MIN);

}

void loop() {

  delay(5);
  radio.startListening();

  if ( radio.available()) {
while (radio.available()) {

      int angleV = 0;
      radio.read(&angleV, sizeof(angleV));
     myServo.write(angleV);
      }

    delay(5);
    radio.stopListening();

  }}

i had tried soo many codes from the internet ... that is your problem ... copy & paste programming ... please do yourself a favor and learn what your existing program is actually doing ... you may find that it is actually easy to add another piece of data to the transmission


text:
ArduinoJson- unexplained '.size()' behaviour
I'm using an ESP8266, ArduinoJson v6.21.5. PlatformIO, and Vscode.
The config file is saved and read correctly to the ESP8266's flash:
{
    "gen_pubTopic": [
        "DvirHome/Messages",
        "DvirHome/log",
        "DvirHome/debug"
    ],
    "subTopic": [
        "DvirHome/Light/int/KitchenLEDs",
        "DvirHome/All",
        "DvirHome/Light/int",
        "DvirHome/Light"
    ],
    "pubTopic": [
        "DvirHome/Light/int/KitchenLEDs/Avail",
        "DvirHome/Light/int/KitchenLEDs/State"
    ]
}

In case the config file is missing, t[], t2[], and t3[] are hard-coded to avoid boot failure.
There are 3 for loops to read topics (from the config file or from hard-coded).
The unexplained part is:

The config file is saved and read as expected, and the code runs without any failure.

when the for loop contains DOC["gen_pubTopic"].size() topics are read as expected, but when it is defined as DOC["gen_pubTopic"].size() |3 it crashes.

x, x2, and x3 are defined before each for loop. Again, once as defined in 2), still no change.

At some part it happened at the 3rd for loop, and sometimes at the 2nd for loop.

Printing xi values shows the expected values.

To make it clear - without using "fallback annotation" |2 the code runs without crashing.

In all stages above - the fallback stage is not tested (meaning- config file is saved and read), and crashes happens when "fallback annotation" is added.

Appreciate any lead why.
void start_iot2(JsonDocument &DOC)
{

  /* Default values */
  const char *t[] = {"DvirHome/Messages", "DvirHome/log", "DvirHome/debug"};
  const char *t2[] = {"DvirHome/Device", "DvirHome/All"};
  const char *t3[] = {"DvirHome/Device/Avail", "DvirHome/Device/State"};

  uint8_t x = DOC["gen_pubTopic"].size() | 3;
  for (uint8_t i = 0; i < x; i++)
  {
    /* Some Code */
    /* debug code */
    Serial.print("Gen_");
    Serial.println(i);
  }

  uint8_t x2 = DOC["subTopic"].size() | 2;
  for (uint8_t i = 0; i < x2; i++)
  {
    /* Some Code */
    /* debug code */
    Serial.print("Sub_");
    Serial.println(i);
  }

  uint8_t x3 = DOC["pubTopic"].size() | 2;
  for (uint8_t i = 0; i < x3; i++)
  {
    /* Some Code */
    /* debug code */
    Serial.print("Pub_");
    Serial.println(i);
  }

  iot.start_services(extMQTT);
}

Edit_1
Added /*debug Code */ to for loops.
At some point, the Serial Monitor showed:
Sub_0
Sub_1
Sub_2
Sub_3
Sub_4
Sub_5

while the size of the SubTopic array is 4 and |2 as default.

I don't know what you expected | 3 to do.

|3 is set as a value in case config file does not exist

I'm afraid that you don't know what | value actually means. Please [edit] your question and describe what you think it does in detail.

|3 is set as a value in case config file does not exist - that isn't what it is doing.

The "fallback notation" you're referring to is JsonVariant::operator| and only works for JsonVariant.
In your program, you apply | to an unsigned long, so the built-in bitwise "or" operator applies. It performs a bit-by-bit "or" operation (for example 2 | 4 is 6).
In other words, doc["key"] | 4 behaves as you describe, but not doc.size() | 4.
Unlike many other languages, you cannot use logical "or" (||) either because it returns a boolean.
So, if you want to make minimal changes to your code, you'll have to do something like this:
uint8_t x = DOC["gen_pubTopic"].size();
if (!x) x = 3;

I prefer explicit conditions instead of hidden C features: if (x == 0) // ... ;-) It does not irritate the casual reader of the source and shows the intention much better.

@Benoit - thank you for a concise answer

I wish to make sure that using iot.add_pubTopic(DOC["pubTopic"][i] | t3[i]); is correct (using t3[i] as "fallback")

Nope, I think not. It looks as if the argument to add_pubTopic is still a unsigned long, for which | means 'bitwise or'. This probably should not even compile, because t3[i] is a string.


text:
Elechouse MP3 shield play random song
Using this code to try and play a random song when someone walks by my distance sensor I get an error, the same song (track 0001) plays every time. Any advice?
#include <SoftwareSerial.h>
SoftwareSerial Geno(7, 8); // Rx, Tx

unsigned char Data[10];
unsigned char i;

// defines pins numbers
const int trigPin = 8;
const int echoPin = 9;

// defines variables
long duration;
int distance;

void setup() {
  delay(1000);
  Geno.begin(9600);
  delay(1000);
  SetVolume(30);
  pinMode(trigPin, OUTPUT); // Sets the trigPin as an Output
  pinMode(echoPin, INPUT); // Sets the echoPin as an Input
  Serial.begin(9600); // Starts the serial communication
}

void playTrack(int num) {
    delay(100);

    Data[0] = 0x7E;
    Data[1] = 0x04;
    Data[2] = 0xA0;
    Data[3] = 0x00;
    Data[4] = 0x00 + num;
    Data[5] = 0x7E;
    Command(Data,5);

    play_pause();

    delay(10000);
}

void SetVolume(int vol) {
   Data[0] = 0x7E; // START
   Data[1] = 0x03; // Length Not 0x02
   Data[2] = 0xA7; // Command
   Data[3] = vol;  // new volume
   Data[4] = 0x7E; // END
   Command(Data,5);
}

void play_pause() {
  Data[0] = 0x7E; // START
  Data[1] = 0x02; // Length
  Data[2] = 0xA3; // Command
  Data[3] = 0x7E; // Mode parameter
  Command(Data,4);
}

void Command(unsigned char *Data, int length) {
  for (int i=0; i<length; i++) {
    Geno.write(Data[i]);
  }
}

void loop() {
  //Assigns a random number
  int song = random(0,200);
  Serial.print("Song is:");
  Serial.print(song);
  Serial.print("\n");
  // Clears the trigPin
  digitalWrite(trigPin, LOW);
  delayMicroseconds(2);

  // Sets the trigPin on HIGH state for 10 micro seconds
  digitalWrite(trigPin, HIGH);
  delayMicroseconds(10);
  digitalWrite(trigPin, LOW);

  // Reads the echoPin, returns the sound wave travel time in microseconds
  duration = pulseIn(echoPin, HIGH);

  // Calculating the distance
  distance = duration * 0.034 / 2;

  Serial.print("Distance: ");
  Serial.println(distance);
  if (distance < 20) {
    playTrack(random(1,25));
  }
  //playTrack(1);
  //playTrack(2);
}

what is the error?

That was bad phrasing on my aprt, the error is it plays the same thing over and over again

start with basic code .... no distance measurement, no random track selection .... only code that plays track 03 (anything other than 01) ... once that works, add random selection .... when that works, add distance sensor code

by its self the play random works but once I add in the code for the distance it play the same song like before, any ideas?

Disclaimer: I know nothing about this media player except what's in this question.  I'd never heard of it before.  The following is simply from observation of the code you posted.
Look at your play_pause() function where the meanings of all the elements are described.
Data[0] = 0x7E;          // START
Data[1] = 0x02;          // Length
Data[2] = 0xA3;          // Command
Data[3] = 0x7E;          //Mode parameter
Command(Data,4);

It seems a message starts with 0x7E, followed by the length , followed by a command and whatever else, followed by another 0x7E.
The length field is 1 less than the total length, so I guess it doesn't include the 'start', or whatever - there are various equivalent ways you could look at it.
In playTrack() you set 6 elements, but with the length element set to 4. You then tell Command() there are 5.  So the last element (0x7E) won't get sent, and the length element which you have sent is wrong anyway.
The receiver is going to get into some weird state, I presume. Perhaps that explains the problem you're seeing.

This is almost definitely a dumb question but I am new to this, where is the length element and where is it set to 4?

I have explained in more detail above.  Hope that makes more sense.

random(1,25) is deterministic. It's PRNG should produce the same sequence of outputs in the same order each time. You need to call randomSeed() at some point, passing it an unpredictable value. Something like:
if(distance < 20){
  randomSeed(micros());
  playTrack(random(1,25));
}


text:
Problem receiving full serial event+SMS
I wrote code in Arduino to read SMS. I have a problem with receiving it from serial.
String str;

void setup() {
  Serial.begin(9600);
  Serial.println("AT+CMGF=1");
  delay(1000);
}

void loop() {
  Serial.println("AT+CMGF=1");
  delay(2000);
  Serial.println("AT+CMGR=1");
  delay(5000);
  while (Serial.available()>0) {
    str = char(Serial.read());
    Serial.print(str);
  }
  Serial.println();
}

I have an A6 GSM modem. When I read the serial I just get:
+CMGR: "REC READ

Nothing more!
I should get something like this:
+CMGL: 1,"REC READ","+989207201219",,"2017/08/26,21:54:56+05"
test 20

I changed my code to:
int readline(int readch, char *buffer, int len) {
  static int pos = 0;
  int rpos;
  if (readch > 0) {
    switch (readch) {
      case '\n': // Ignore new-lines
        break;
      case '\r': // Return on CR
        rpos = pos;
        pos = 0;  // Reset position index ready for next time
        return rpos;
      default:
        if (pos < len-1) {
          buffer[pos++] = readch;
          buffer[pos] = 0;
        }
    }
  }
  // No end of line has been found, so return -1.
  return -1;
}

void setup() {
  Serial.begin(9600);
  Serial.println("AT+CMGF=1");
  Serial.println("AT+CPMS=\"SM\",\"SM\",\"SM\"");
}

void loop() {
  Serial.println("AT+CMGF=1");
  Serial.println("AT+CMGR=1");
  static char buffer[80];
  if (readline(Serial.read(), buffer, 80) > 0) {
    Serial.print("You entered: >");
    Serial.print(buffer);
    Serial.println("<");
  }
  delay(3000);
}

But I get nothing.

I didnt get the answer there

Did you read that you shouldn't delay?

I remove the delays, But didint get anything at all

I need a clean code to understand :(

I seem to post this same link about 10 times every day. I do wish people would learn the basics... https://hackingmajenkoblog.wordpress.com/2016/02/01/reading-serial-on-the-arduino/

Have you not noticed that you are doing two things with just one thing? I.e., you are using Serial for two purposes? Which do you want to use it for - communication with your modem, or communication with the PC? Make your mind up.

@Majenko I want to communicate with the modem, read the sms and do something based on what sms contain

I changed the code. so It works fine
String inputString = "";         // a String to hold incoming data
void setup() {
  // put your setup code here, to run once:
  Serial.begin(9600);
  Serial.println("AT+CMGF=1");
  Serial.println("AT+CPMS=\"SM\",\"SM\",\"SM\"");
}

void loop() {

  Serial.println("AT+CMGR=1");

}

void serialEvent() {
    inputString = Serial.readString();
    Serial.println(inputString);
    delay(5000);
  }

The arduino is a "small memory" device. So it probably does not have a big serial buffer. On say "linux on a PC" you get a 4096 byte buffer, but on an arduino, probably only say 16. Now as luck will have it "+CMGR: "REC READ" is precisely 16 characters....
From the code that I see, you seem to be sending commands to the modem and then reading/echoing them. I would have liked to use two different serial ports or something like that.
In any case, if it sort of works for those first 16 characters, remove all the delays and put one of them near the end of the loop() function. Remove the initial print to the modem in the setup function.

I get more characters too. sometimes more than 30 characters.


text:
rylr498 receiver problem
I have a problem receiving heart rate message tranmission data from the reciever. I was able ot transmit the data from the trasnmitter but I am unavke to recieve the data from the reciever side. This is the code for the transmitter and reciever respectively
transmitter code:
#include <PulseSensorPlayground.h> // Include the PulseSensor library

String lora_band = "490000000";  // enter band as per your country
String lora_networkid = "5";     // enter Lora Network ID
String lora_address = "1";        // enter Lora address
String lora_RX_address = "2";     // enter Lora RX address
int Threshold = 550;           // Determine which Signal to "count as a beat" and which to ignore

PulseSensorPlayground pulseSensor;  // Creates an object
void setup() {
  Serial.begin(57600);
  delay(1500);
  Serial.println("AT+BAND=" + lora_band);
  delay(500);
  Serial.println("AT+ADDRESS=" + lora_address);
  delay(500);
  Serial.println("AT+NETWORKID=" + lora_networkid);
  delay(1500);

  // Initialize PulseSensor
  pulseSensor.analogInput(A0); // Assuming your pulse sensor is connected to analog pin A1
  pulseSensor.blinkOnPulse(LED_BUILTIN); // Blink onboard LED with heartbeat
  pulseSensor.setThreshold(Threshold);

  // Double-check if PulseSensor object was created and began seeing a signal
  if (pulseSensor.begin()) {
    Serial.println("PulseSensor object created!");
  }
}

void loop() {
  int myBPM = pulseSensor.getBeatsPerMinute(); // Calculate BPM

  if (pulseSensor.sawStartOfBeat()) { // Constantly test if a beat happened
    Serial.println("♥  A HeartBeat Happened ! "); // If true, print a message
    Serial.print("BPM: ");
    Serial.println(myBPM); // Print the BPM value
    Serial.println("AT+SEND=" + lora_RX_address + ",2,H" + String(myBPM)); // Send a LoRa message when a heartbeat is detected
  }

  // You can add additional LoRa message sending logic here, depending on your requirements

  delay(20); // Small delay to avoid excessive CPU usage
}

receiver code:
String lora_band = "490000000";   // Enter band as per your country
String lora_networkid = "5";     // Enter Lora Network ID
String lora_address = "2";        // Enter Lora address (receiver address)
String lora_RX_address = "1";     // Enter Lora RX address

void setup() {
  Serial.begin(57600);
  delay(1500);
  Serial.println("AT+BAND=" + lora_band);
  delay(500);
  Serial.println("AT+ADDRESS=" + lora_address);
  delay(500);
  Serial.println("AT+NETWORKID=" + lora_networkid);
  delay(1500);
}

void loop() {
  if (Serial.available() > 0) { // Check if data is available to read from LoRa module
    String receivedData = Serial.readStringUntil('\n'); // Read the incoming data until newline character
    if (receivedData.startsWith("AT+SEND=")) { // Check if received data starts with "AT+SEND="
      String message = receivedData.substring(8); // Extract message (excluding "AT+SEND=")
      Serial.println("Received message: " + message);
    }
  }
  delay(20); // Small delay to avoid excessive CPU usage
}

Kindly assist me on this problem.

How did you connect your Lora module with your Arduino Nano? Serial.print() send the data to your Serial Monitor, it does not send to the serial port of the Lora module, you will need SoftwareSerial library for communication with Lora module, on both the transmitter and the receiver.

I was able ot transmit the data from the trasnmitter ... how do you know this?

I connected the tx to rx and rx to tx in the arduino nano for reciever and transmitter. i used 4.7k and 10k ohm pull up resistor to make sure the voltage is 3.3v.

The tx light glows each time the heartbeat reading is detected.