text:
How to handle an interrupt that interrupts a serial communication?
I am at the moment trying via ros to publish a status message about how many steps a motor has moved.
Problem, is that value doesn't to be readable, or the only thing I am able to read from the topic is a zero.
The value i want to publish is being incremented inside a ISR routine, so i have a single thread that continuesly publishes the messages, and then when an ISR is called, increment it the value.
I tested with serial to see what might have been wrong, but the output of the serial doesn't seem to make any sence, isn't readable.. Is outputs alot of "??" eventhoug I am using the right baudrate and so on. So what is the problem here?
speed_profile.cpp
#include "speed_profile.h"

volatile speed_profile profile;
ros::NodeHandle nh;

std_msgs::Int16 status_step_count;
ros::Publisher chatter("tipper_status", &status_step_count);

void output_pin_setup()
{
  pinMode(en_pin,OUTPUT);
  pinMode(dir_pin,OUTPUT);
  pinMode(step_pin,OUTPUT);
  nh.initNode();
  nh.advertise(chatter);
}

void timer1_setup()
{
  // Tells what part of speed ramp we are in.
  profile.run_state = STOP;

  // Timer/Counter 1 in mode 4 CTC (Not running).
  TCCR1B = (1 << WGM12);

  // Timer/Counter 1 Output Compare A Match Interrupt enable.
  TIMSK1 = (1 << OCIE1A);
}

void compute_speed_profile(signed int motor_steps, unsigned int motor_accel, unsigned int motor_decel, unsigned int motor_speed)
{
  digitalWrite(en_pin,HIGH);
  delay(1);

  unsigned int steps_to_speed;  // Steps required to achieve the the speed desired
  unsigned int acceleration_step_limit; // If desired speed is not achieved, will this variable contain step_limit to when to stop accelerating.

  if (motor_steps < 0)
  {
    profile.dir = CCW;
    motor_steps = -motor_steps;
    digitalWrite(dir_pin,LOW);
  }
  else
  {
    profile.dir = CW;
    digitalWrite(dir_pin,HIGH);
  }

  delay(1);

  // If moving only 1 step.
  if (motor_steps == 1)
  {
    // Move one step
    profile.accel_count = -1;
    // in DECEL state.
    profile.run_state = DECEL;
    // Just a short delay so main() can act on 'running'.
    profile.first_step_delay = 1000;
    OCR1A = 10;
    // Run Timer/Counter 1 with prescaler = 8.
    TCCR1B |= ((0 << CS12) | (1 << CS11) | (0 << CS10));
  }
  else if (motor_steps != 0)
  {
    // Set max speed limit, by calc min_delay to use in timer.
    // min_delay = (alpha / tt)/ w
    profile.min_time_delay = A_T_x100 / motor_speed;

    // Set accelration by calc the first (c0) step delay .
    // first_step_delay = 1/tt * sqrt(2*alpha/accel)
    // first_step_delay = ( tfreq*0.676/100 )*100 * sqrt( (2*alpha*10000000000) / (accel*100) )/10000
    profile.first_step_delay = (T1_FREQ_148 * sqrt(A_SQ / motor_accel)) / 100;

    // Find out after how many steps does the speed hit the max speed limit.
    // steps_to_speed = speed^2 / (2*alpha*accel)
    steps_to_speed = (long)motor_speed * motor_speed / (long)(((long)A_x20000 * motor_accel) / 100);
    // If we hit max speed limit before 0,5 step it will round to 0.
    // But in practice we need to move atleast 1 step to get any speed at all.
    if (steps_to_speed == 0)
    {
      steps_to_speed = 1;
    }

    // Find out after how many steps we must start deceleration.
    // n1 = (n1+n2)decel / (accel + decel)
    acceleration_step_limit = ((long)motor_steps * motor_decel) / (motor_accel + motor_decel);
    // We must accelrate at least 1 step before we can start deceleration.
    if (acceleration_step_limit == 0)
    {
      acceleration_step_limit = 1;
    }

    // Use the limit we hit first to calc decel.
    if (acceleration_step_limit <= steps_to_speed)
    {
      //profile.decel_length = steps_to_speed - motor_steps;
      profile.decel_length = -(motor_steps-acceleration_step_limit); //---
    }
    else
    {
      //profile.decel_length = -((long)steps_to_speed * acceleration_step_limit) / motor_decel;acceleration_step_limit
      profile.decel_length = -((long)steps_to_speed * motor_accel) / motor_decel; //--
    }
    // We must decelrate at least 1 step to stop.
    if (profile.decel_length == 0)
    {
      profile.decel_length = -1;
    }

    // Find step to start decleration.
    //int steps_in_run = motor_steps - steps_to_speed-profile.decel_length;

    profile.decel_start = motor_steps + profile.decel_length;
    //profile.decel_start = motor_steps - steps_to_speed-steps_in_run;

    // If the maximum speed is so low that we dont need to go via accelration state.
    if (profile.first_step_delay <= profile.min_time_delay)
    {
      profile.first_step_delay = profile.min_time_delay;
      profile.run_state = RUN;
    }
    else
    {
      profile.run_state = ACCEL;
    }

    // Reset counter.
    profile.accel_count = 0;
    OCR1A = 10;
    // Set Timer/Counter to divide clock by 8
    TCCR1B |= ((0 << CS12) | (1 << CS11) | (0 << CS10));
    profile.moved_steps = 0;

  }

  while(1)
  {
    cli();
    status_step_count.data = profile.moved_steps;
    Serial.print("profile.moved_steps: ");
    Serial.println(profile.moved_steps);
    Serial.print('\n');
    sei();
    //chatter.publish( &status_step_count);
    //nh.spinOnce();
    delay(1);
  }

}

ISR(TIMER1_COMPA_vect)
{
  // Holds next delay period.
  unsigned int new_first_step_delay;

  // Remember the last step delay used when accelrating.
  static int last_accel_delay;

  // Counting steps when moving.
  static unsigned int step_count = 0;

  // Keep track of remainder from new_step-delay calculation to incrase accurancy
  static unsigned int rest = 0;

  OCR1A = profile.first_step_delay;

  switch (profile.run_state)
  {

    case STOP:
      step_count = 0;
      rest = 0;
      TCCR1B &= ~((1 << CS12) | (1 << CS11) | (1 << CS10)); // Stop the timer,  No clock source
      break;

    case ACCEL:
      digitalWrite(step_pin,!digitalRead(step_pin));
      //delay(1);
      //digitalWrite(step_pin,LOW);
      step_count++;
      profile.accel_count++;
      new_first_step_delay = profile.first_step_delay - (((2 * (long)profile.first_step_delay) + rest) / (4 * profile.accel_count + 1));
      rest = ((2 * (long)profile.first_step_delay) + rest) % (4 * profile.accel_count + 1);

      // Chech if we should start decelration.
      if (step_count >= profile.decel_start)
      {
        profile.accel_count = profile.decel_length;
        profile.run_state = DECEL;
      }

      // Chech if we hitted max speed.
      else if (new_first_step_delay <= profile.min_time_delay)
      {
        last_accel_delay = new_first_step_delay;
        new_first_step_delay = profile.min_time_delay;
        rest = 0;
        profile.run_state = RUN;
      }
      break;
    case RUN:
      digitalWrite(step_pin,!digitalRead(step_pin));

      //delay(1);
      //digitalWrite(step_pin,LOW);
      step_count++;
      new_first_step_delay = profile.min_time_delay;
      // Chech if we should start decelration.
      if (step_count >= profile.decel_start)
      {
        profile.accel_count = profile.decel_length;
        // Start decelration with same delay as accel ended with.
        new_first_step_delay = last_accel_delay;
        profile.run_state = DECEL;
      }
      break;
    case DECEL:
      digitalWrite(step_pin,!digitalRead(step_pin));
      step_count++;
      profile.accel_count++;
      new_first_step_delay = profile.first_step_delay - (((2 * (long)profile.first_step_delay) + rest)/(4 * profile.accel_count + 1));
      rest = ((2 * (long)profile.first_step_delay)+rest)%(4 * profile.accel_count + 1);
      // Check if we at last step
      //digitalWrite(step_pin,!digitalRead(step_pin));
      if(profile.accel_count >= 0)
      {
        digitalWrite(en_pin,!digitalRead(en_pin));
        profile.run_state = STOP;
      }

      break;

  }
    profile.first_step_delay = new_first_step_delay;
    profile.moved_steps = step_count;
}

speed_profile.h
#ifndef speed_profile_h
#define speed_profile_h

#include <Arduino.h>
#include <ros.h>
#include <std_msgs/Int16.h>

// Timer/Counter 1 running on 3,686MHz / 8 = 460,75kHz (2,17uS). (T1-FREQ 460750)
//#define T1_FREQ 460750
#define T1_FREQ 1382400

//! Number of (full)steps per round on stepper motor in use.
#define FSPR 1600

// Maths constants. To simplify maths when calculating in compute_speed_profile().
#define ALPHA (2*3.14159/FSPR)                    // 2*pi/spr
#define A_T_x100 ((long)(ALPHA*T1_FREQ*100))     // (ALPHA / T1_FREQ)*100
#define T1_FREQ_148 ((int)((T1_FREQ*0.676)/100)) // divided by 100 and scaled by 0.676
#define A_SQ (long)(ALPHA*2*10000000000)         // ALPHA*2*10000000000
#define A_x20000 (int)(ALPHA*20000)              // ALPHA*20000

// Speed ramp states
#define STOP  0
#define ACCEL 1
#define DECEL 2
#define RUN   3

// Pin numbering
#define en_pin 13
#define dir_pin 12
#define step_pin 11

// Motor direction
#define CW  0
#define CCW 1

typedef struct
{
 volatile unsigned char run_state : 3; // Determining the state of the speed profile
 volatile unsigned char dir: 1; // Determining the direction the motor has to move - Start being CCW
 volatile unsigned int first_step_delay; // Period time for the next timer_delay, determines the acceleration rate.
 volatile unsigned int decel_start; //  Determines at which step the deceleration should begin.
 volatile signed int decel_length; // Set the deceleration length
 volatile signed int min_time_delay; //minium time delay c0
 volatile signed int accel_count; // counter used when computing step_delay for acceleration/decelleration.
 volatile unsigned int moved_steps; // Used by ros to publish current tipper position

}speed_profile;

void compute_speed_profile(signed int motor_steps, unsigned int motor_accel, unsigned int motor_decel, unsigned int motor_speed);
void timer1_setup(void);
void output_pin_setup(void);
#endif

main.ino
#include "speed_profile.h"

void setup() {
  // put your setup code here, to run once:
  cli();
  Serial.begin(9600);
  output_pin_setup();
  timer1_setup();
  sei();
}

void loop()
{
  // put your main code here, to run repeatedly:
    Serial.println("\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n");

    int motor_steps = -3000;//-9600; //23400 -  100%
    // Accelration to use.
    int motor_acceleration = 500;//500;
    // Deceleration to use.
    int motor_deceleration = 500;//500;
    // Speed to use.
    int motor_speed = 1000; // 1000
    compute_speed_profile(motor_steps, motor_acceleration, motor_deceleration, motor_speed);
    while(1)
    {

    }
}

Could you add least add the entire code at the end. I'm unable to decipher what is going on with just the snippets you posted. Could you also add some sample output of the serial?

I just found out that it works with an baudrate of 57600, eventhough I initiliaze it to 9600.

full code added.

What Arduino do you have, and what clock frequency is it running at?

This is highly inadvisable:

cli();
status_step_count.data = profile.moved_steps;
Serial.print("profile.moved_steps: ");
Serial.println(profile.moved_steps);
Serial.print('\n');
sei();

Doing serial prints with interrupts off could hang your sketch because the Serial output routines require interrupts on to work.
Later versions of the IDE might not hang completely but will block until the data can be written.

The problem may be due to something you haven't told us about, so the following suggestions are just general ideas.
First, try out whether serial communication works ok at 230400 when your stepper code isn't running.  For example, add some debug lines to skip over whatever code turns on interrupts to run the stepper, and see if serial  communication is ok.
If serial  communication still fails with stepper interrupts off, try lower serial rates, eg 19200 or 9600.  In addition, in your Publisher add a reasonable delay, eg half a second or a second, between serial writes.  You might also not issue a write whenever the total steps has changed less than a hundred counts, or some similar number.
I'd probably factor toggling step_pin out of the switch, via code like the following.
if (profile.run_state != STOP) {
   // Toggle step_pin by writing 1 to its bit in PINB
   PINB = step_pin_mask; // pin 11 = PB3, so mask is 1<<PB3, ie, 1<<3
   step_count++;
}
switch (profile.run_state) {
   ...

Using digitalRead() and digitalWrite() adds a fair amount of overhead, undesirable in an ISR.  (See their source code at garretlab links, digitalRead() and digitalWrite()) That extra overhead could possibly account for glitches in serial communications.
By contrast, writing a mask bit to an input port is about the fastest way for software to toggle a bit or set of bits.  It is, of course, less flexible and less obvious.

I am not sure what else would be missing than the complete code.. but thanks for the pointers with make it faster..  it is a lot of code, and I am doing a sqrt() operation somewhere, so it would be very use full to compensate for that.

That is QUITE a high baud rate. You might want to lower it. I know that Arduinos running at 8MHZ can barely handle 112500. Do not push it too far. I do not know what Arduino you are using but at 16MHZ, don't push it too far. Also make sure that at that baud rate you supply a lot of juice to your Arduino so that it can run more smoothly.

i tried with 9600 and same result

Sorry I couldn't help.


text:
Deactivate pushbuttons at initial stage
Pl someone answer my question. I have 4 pushbuttons namely add/reject/start & finish. I want to
1.Deactivate add/reject buttons at initial stage until start button pressed &
2.Once add/reject activated, again should deactivate once finish button pressed &
3.Again if start button pressed, add/reject should be released.
with following code I able to do 2 & 3. However I still lack at 1.pl help on this.
const int bt_Select = 2; // #define BUTTON_PIN 2
const int bt_Reject = 3;
const int bt_Start = 7;
const int bt_Finish = 8;

boolean decision=false;

int bt_Select_state=0;
int bt_Reject_state=0;
int bt_Start_state;
int bt_Finish_state;

int selected;
int rejected;
int started;
int finished;

void setup() {
  // put your setup code here, to run once:
    Serial.begin(9600);
    pinMode(bt_Select, INPUT_PULLUP);
    pinMode(bt_Reject, INPUT_PULLUP);
    pinMode(bt_Finish, INPUT_PULLUP);
    pinMode(bt_Start, INPUT_PULLUP);
    Serial.println("Welcome to Nano");
    delay(1000);
  }
//========================================================================
      void loop() {

        started=bt_Start_pressed();
        selected =bt_Select_pressed();
        rejected=bt_Reject_pressed();
        finished=bt_Finish_pressed();
        decision=Stop_Main();

          int x=0;
          int Lx=0;

       if (selected&&decision){x=1;}
       if (rejected&&decision){x=2;}
        if (started&&decision){x=3;}

       if (x!=Lx){
        switch(x) {
          case 1:Serial.println("Selected");delay(250);Serial.print("");
                 break;
          case 2:Serial.println("Rejected");delay(250);Serial.print("");
                 break;
          case 3:Serial.println("Started");delay(250);Serial.print("");
                 break;

          /*case 3://do something when var equals 1
                 Serial.println("Removed");
                 break; */
             }//switch(x)
                 x=Lx;
      }//eof  if (x!=Lx)

      }
//====================================================================
      int bt_Select_pressed(){
         bt_Select_state=digitalRead(bt_Select);
           if (bt_Select_state == LOW){return 1;}
           else {return 0;}
      }
//====================================================================
      int bt_Reject_pressed(){
         bt_Reject_state=digitalRead(bt_Reject);
          if (bt_Reject_state == LOW){return 1;}
          else {return 0;}
           }
//====================================================================
    int bt_Start_pressed(){
         bt_Start_state=digitalRead(bt_Start);
          if (bt_Start_state == LOW){return 1;}
          else{return 0;}
            }
//====================================================================
      int bt_Finish_pressed(){
        bt_Finish_state=digitalRead(bt_Finish);
          if (bt_Finish_state == LOW){return 1;}
          else {return 0;}
      }
//=====================================================================

      boolean Stop_Main(){
        bt_Start_state=digitalRead(bt_Start);
        bt_Finish_state=digitalRead(bt_Finish);

        if (bt_Finish_state == LOW){decision=false;return decision;}
        if (bt_Start_state == LOW){decision=true; return decision;}

       // else if (bt_Start_state ==HIGH  && bt_Finish_state == HIGH){decision=false;return decision;}
          }

/*  boolean bt_Start_pressed(){
         bt_Start_state=digitalRead(bt_Start);
          if (bt_Start_state == LOW){started=true; return decision;}
          else{started=false; return decision;}
            }   */
    //===================

you are not thinking clearly about the problem ... it is not deactivate button ... it is ignore button ... use a state variable like bt_Start_state ... just ignore add/reject buttons until the state variable is true

Keep a boolean that begins as false. Set it to true when the start button is pressed, and set it to false again when the finish button is pressed. Then you can read and respond to the add and reject buttons only if that boolean is true, and otherwise ignore them.

source: Stack Exchange

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

sort: votes


text:
lcd byte array display
when reading RFID(MIFARE) information using Arduino mega and display in serial monitor it works fine. But, when printing on 2004LCD only one information(Value) displays correctly. The other information Item Name display a decimal number. Could someone help on this?
 void Price(){
      block = 4;
      status = mfrc522.PCD_Authenticate(MFRC522::PICC_CMD_MF_AUTH_KEY_A, 4, &key, &(mfrc522.uid));
      if (status != MFRC522::STATUS_OK) {
        Serial.print(F("Authentication failed: "));
        Serial.println(mfrc522.GetStatusCodeName(status));
        return;
      }
      status = mfrc522.MIFARE_Read(block, buffer1, &len);  // ***Note down buffer1 within the bracket
      if (status != MFRC522::STATUS_OK) {
        Serial.print(F("Reading failedl: "));
        Serial.println(mfrc522.GetStatusCodeName(status));
        return;
      }
             //Display price information...
      for (uint8_t i = 0; i < 16; i++)
      {
        if (buffer1[i] != 32) // if buffer1[i] not equal to 32
        {
          Serial.write(buffer1[i]);  //Price
         //lcd.write(buffer1[i]);
          Value = buffer1[i];
          }
       }
      Serial.print("/=");
      Serial.println(" ");
      sscanf(buffer1,"%d",&Value);
      lcd.setCursor(0,1);
      lcd.println(Value);

     }
    //==========================================================
    void Item(){ //----- Get & Display Item information
        block = 1;
     status = mfrc522.PCD_Authenticate(MFRC522::PICC_CMD_MF_AUTH_KEY_A, 1, &key, &(mfrc522.uid));
      if (status != MFRC522::STATUS_OK) {
        Serial.print(F("Authentication failed: "));
        Serial.println(mfrc522.GetStatusCodeName(status));
        return;
      }
      status = mfrc522.MIFARE_Read(block, buffer2, &len);
      if (status != MFRC522::STATUS_OK) {
        Serial.print(F("Reading failed: "));
        Serial.println(mfrc522.GetStatusCodeName(status));
        return;
      }
      for (uint8_t i = 0; i < 16; i++) { //
         Serial.write(buffer2[i]);       // Display Item
         lcd.write(buffer2[i]);
         Item_Name=buffer2[i];
        }
        sscanf(buffer2,"%s",&Item_Name);
       //sprintf(buffer2,"%d",&Item_Name);
          lcd.clear();
          lcd.setCursor(0,0);
          lcd.print(Item_Name);// displays numbers instead of "Fresh Milk 1Lt
     }

What is the data type of Item_Name?

data type is int

sscanf(buffer2,"%s",&Item_Name); works however return a number instead an string.

Consider the following:
char buffer2[16];  // array of 16 chars
for (uint8_t i = 0; i < 16; i++) {
    do_something_with(buffer2[i]);  // handle one char at a time
}

Here we have an array of 16 cells, each having the char type (which I
assume is what you have). The loop goes through the array, handling one
cell a time. Within the loop, buffer2[i] represents the char being
currently handled.
Keep in mind that a char is just an 8-bit integer. It is somehow
implied that it is meant to represent a character, where 32 = ' '
(space), 33 = '!', 48 = '0', 65 = 'A' and so on (see ASCII).
The Arduino print() methods do assume a char (unlike an int) is
intended to be displayed as a character.
Now your actual loop:
int Item_Name;
for (uint8_t i = 0; i < 16; i++) {
    Serial.write(buffer2[i]);  // write the char on the serial port
    lcd.write(buffer2[i]);     // write the char on the LCD
    Item_Name=buffer2[i];      // store the char in a variable
}

This will print the contents of the buffer to both the serial port and
the LCD. You would have seen the expected message on the LCD if you did
not have lcd.clear() right after the loop.
sscanf(buffer2, "%s", &Item_Name);

This means “extract from buffer2 a sequence of contiguous
non-white-space characters, and store it in memory at the address of the
variable ItemName”. If the buffer contains “Fresh Milk 1Lt”, this will
write “Fresh” to that memory location. That is 6 bytes (5 letters and a
terminating NUL). Unfortunately, the compiler has only allocated 2 or
4 bytes of RAM for storing ItemName (depending on the Arduino model),
so this will write past the allocated storage, which is a type of bug
known as buffer overflow. Now your Arduino's memory is corrupted and
anything can happen.
sprintf(buffer2, "%d", &Item_Name);

This tries to find within byffer2 a textual representation of a
number, and store it into Item_Name. This is safe, but only makes
sense if the buffer contains a number, written as text, which is not the
case here.
lcd.print(Item_Name);

This is asking the LCD to print an integer (namely Item_Name). It will
convert the integer to decimal text and print the corresponding digits
on the LCD.
Let's assume for example that Item_Name contains the numeric value
32 (which is the ASCII representation of a space). lcd.print() will
convert that into a sequence of two characters: '3' and '2' (the
decimal representation of 32). It will then send those characters to the
LCD (ASCII values 51 and 50), and you will see the text “32”.
If you want to see the text contained within the buffer, the you can
either send the characters one by one (like you already did right before
lcd.clear()), or provide to lcd.print() a char* pointer with the
whole message:
lcd.print(buffer2);

This assumes that the buffer is terminated with a NUL character. If it
is not, then you can either use the char-at-a-time method, or change
your code in order to put a NUL terminator in the buffer.

Thank you so much! it's working when i change the data type of buffer2 from byte array to character array

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


text:
Attempting to monitor serial output for a string to trigger function, apparently matching string is output but the function doesn't trigger
I'm working on my second Arduino project, and am somewhat stuck.
I'm running a PIR module from my Arduino Uno with the following sketch:
/*
 *  PIR Sensor test
 */

 int pirPin = 6;

 int minSecsBetweenEmails = 60; // 60 seconds

 long lastSend = -minSecsBetweenEmails * 1000l;

 void setup()
 {
  pinMode(pirPin, INPUT);

  Serial.begin(9600);
 }

 void loop() {
  long now = millis();
  if (digitalRead(pirPin) == HIGH)
    {
       if (now > (lastSend + minSecsBetweenEmails * 1000l))
        {
            Serial.println("MOVEMENT");
            lastSend = now;
        }
      else
        {
          Serial.println("Too soon");
        }
    }
        delay(500);
 }

I'm monitoring the COM3 port using the following in JupyterLab with PySerial.
import time
import serial
import smtplib

to = 'myemail@myemail.com'
GMAIL_USER = 'myemail@myemail.com'
GMAIL_PASS = '**********'

SUBJECT = 'MOTION pir'
TEXT = 'PIR sensor detected motion'

ser = serial.Serial('COM3', 9600)

def send_email():
    print("Sending Email")
    smtpserver = smtplib.smtp("smtp.gmail.com",587)
    smtpserver.ehlo()
    smtpserver.starttls()
    smtpserver.ehlo
    smtpserver.login(GMAIL_USER, GMAIL_PASS)
    header = str('To:' + TO + '\n' + 'From: ' + GMAIL_USER)
    header = header + '\n' + 'Subject:' + SUBJECT + '\n'
    print (header)
    msg - header + '\n' + TEXT + ' \n\n'
    smtpserver.sendmail(GMAIL_USER, TO, msg)
    smtpserver.close()

while True:
        message = ser.readline()
        print(message.decode('utf-8'))
        if message[0] == 'MOVEMENT' :
            send_email()
            time.sleep(0.5)

I believe my problem is with the ser.readline() function. I've been reading the docs, they seem to say I need to provide some kind of endpoint or timeout for the function to provide for EOF, but my goal was to have the
if message [0] == 'MOVEMENT' :

continuously evaluate the output lines from COM3...
Any input at all would be very much appreciated.
EDIT: Thanks to all three of you for your help! By changing the Python as shown below I was able to fulfill the if message[0] == 'MOVEMENT' :statement
Python should have been:
import time
import serial
import smtplib

to = 'myemail@myemail.com'
GMAIL_USER = 'myemail@myemail.com'
GMAIL_PASS = '**********'

SUBJECT = 'MOTION pir'
TEXT = 'PIR sensor detected motion'

ser = serial.Serial('COM3', 9600)

def send_email():
    print("Sending Email")
    smtpserver = smtplib.smtp("smtp.gmail.com",587)
    smtpserver.ehlo()
    smtpserver.starttls()
    smtpserver.ehlo
    smtpserver.login(GMAIL_USER, GMAIL_PASS)
    header = str('To:' + TO + '\n' + 'From: ' + GMAIL_USER)
    header = header + '\n' + 'Subject:' + SUBJECT + '\n'
    print (header)
    msg - header + '\n' + TEXT + ' \n\n'
    smtpserver.sendmail(GMAIL_USER, TO, msg)
    smtpserver.close()

while True:
        message = ser.readline()
        print(message)
        if message == b'MOVEMENT\r\n' :
            send_email()
            time.sleep(0.5)

Use the serial console to see what the Arduino is sending. If it is sending what you expect, then it is working properly, your problem lies in your Python code, and your question does not belong to this site. If it is not sending what you expect, then remove all the Python/SMTP stuff from your question, and make it focused on the Arduino sketch.

The readline usually reads line ending characters too. Are you sure it's not the case?

And are you sure you are not comparing first character from the message with whole string 'MOVEMENT'?

Note that your timing test will fail when millis() rolls over. You should rather write if (now - lastSend > minSecsBetweenEmails * 1000l), which is rollover-safe.

Edgar, thanks for the heads-up about the millis() rollover. I guess I misunderstood the breadth of this specific StackExchange community, I was under the impression that since I'm dealing with a specific Arduino implementation it would be relevant here, but I guess not. The Uno's output is exactly what I expect, so I'm thinking it's more of a Python issue.
KIIV, as to your first comment, I've tried to add the line ending characters to the string since I'm getting the correct output from the Uno, but no luck yet.

You're confusing readlines() with readline().  The former returns an array of lines, the latter a single line.  You need to drop the [0] since you're not working with an array of lines, and you need to include the line endings that the Arduino sends:
while True:
    message = ser.readline()
    print(message.decode('utf-8'))
    if message == 'MOVEMENT\r\n' :
        send_email()
        time.sleep(0.5)

Thanks Majenko. You're correct on my confusion between those functions. I've attempted to add the line ending characters but have yet to fulfill the if statement, so I'm going to continue investigating where I screwed up.


text:
LCD Blinking after inserting code : A medication reminder system using Arduino Uno
RTC DS3231,Arduino Uno and 4 push buttons, 10K potentiometer, 4 of 10K resistor and a buzzer. I decided to follow from an online source and encounters a few problems which already fixed but this one puzzles me. Would really appreciate your help. The RTClib.h library is already installed.LCD Blinking after inserting code and it shows blocks instead of characters.
There's other picture in this link too.
https://drive.google.com/open?id=1OzHqZlS7mnkngMx-EIiqIgzdHZaTsHr8

#include <LiquidCrystal.h>
#include <Wire.h>
#include <RTClib.h>
#include <EEPROM.h>

RTC_DS3231 rtc;

const int rs = 12, en = 11, d4 = 5, d5 = 4, d6 = 3, d7 = 2;                 // lcd pins
LiquidCrystal lcd(rs, en, d4, d5, d6, d7);

int buzz = 13;
int addr=17;

const int buttonPin2 = 9;
const int buttonPin3 = 8;
const int buttonPin1 = A0;
const int buttonPin4 = 7; // the pin that the pushbutton is attached to
int val2 = 0;
int val3=0;
int pushVal;
int bS1 = 0;         // current state of the button
int lBS1 = 0;     // previous state of the button

int bS2 = 0;         // current state of the button
int lBS2 = 0;

int bS3 = 0;         // current state of the button
int lBS3 = 0;

int bS4 = 0;         // current state of the button
int lBS4 = 0;

// configure the pins to the right mode
int buzz8amHH = 8;          //    HH - hours         ##Set these for reminder time in 24hr Format
int buzz8amMM = 00;          //    MM - Minute
int buzz8amSS = 00;          //    SS - Seconds

int buzz2pmHH = 8;          //    HH - hours
int buzz2pmMM = 1;          //    MM - Minute
int buzz2pmSS = 00;          //    SS - Seconds

int buzz8pmHH = 8;          //    HH - hours
int buzz8pmMM = 2;          //    MM - Minute
int buzz8pmSS = 00;          //    SS - Seconds

int nowHr, nowMin, nowSec;

void gwsMessege(){               // print get well soon messege
    lcd.clear();
    lcd.setCursor(0, 0);
    lcd.print("Stay Healthy :)");     // Give some cheers
    lcd.setCursor(0, 1);
    lcd.print("Get Well Soon :)");// wish
}

void helpScreen() {              // function to display 1st screen in LCD
    lcd.clear();
    lcd.setCursor(0, 0);
    lcd.print("Press Buttons");
    lcd.setCursor(0, 1);
    lcd.print("for Reminder...!");
 }

void timeScreen() {              // function to display Date and time in LCD screen
  DateTime now = rtc.now();             // take rtc time and print in display
    lcd.clear();
    lcd.setCursor(0, 0);
    lcd.print("Time:");
    lcd.setCursor(6, 0);
    lcd.print(nowHr = now.hour(), DEC);
    lcd.print(":");
    lcd.print(nowMin = now.minute(), DEC);
    lcd.print(":");
    lcd.print(nowSec = now.second(), DEC);
    lcd.setCursor(0, 1);
    lcd.print("Date: ");
    lcd.print(now.day(), DEC);
    lcd.print("/");
    lcd.print(now.month(), DEC);
    lcd.print("/");
    lcd.print(now.year(), DEC);
    delay(500);
}

void setup()
{
Wire.begin();
  rtc.adjust(DateTime(F(__DATE__), F(__TIME__)));            // uncomment this to set the current time and then comment in next upload when u set the time
  //rtc.adjust(DateTime(2019, 1, 10, 7, 59, 30));                // manual time set

  lcd.begin(16, 2);
  lcd.clear();
  lcd.setCursor(0, 0);
  lcd.print("Welcome To Our");                                      // print a messege at startup
  lcd.setCursor(0, 1);
  lcd.print("Medicine Reminder");
  delay(1000);
  gwsMessege();
  delay(3000);
  helpScreen();
  delay(2000);
  timeScreen();
  delay(3000);
  lcd.clear();

  pinMode(buttonPin1, INPUT);
  pinMode(buttonPin2, INPUT);
  pinMode(buttonPin3, INPUT);
  pinMode(buttonPin4, INPUT);
  pinMode(buzz, OUTPUT);
  Serial.begin(9600);
}

void ValSet(){
  Serial.println(EEPROM.read(addr));
  val2 = EEPROM.read(addr);                         // read previosuly saved value of push button to start from where it was left previously
  switch (val2) {
    case 1:
      lcd.clear();
    lcd.setCursor(0, 0);
    lcd.print("Reminder set ");
    lcd.setCursor(0, 1);
    lcd.print("for Once/day !");
      pushVal = 1;
      delay(500);
      break;
    case 2:
      lcd.clear();
    lcd.setCursor(0, 0);
    lcd.print("Reminder set ");
    lcd.setCursor(0, 1);
    lcd.print("for Twice/day !");
      pushVal = 2;
      delay(500);
      break;
    case 3:
      lcd.clear();
    lcd.setCursor(0, 0);
    lcd.print("Reminder set ");
    lcd.setCursor(0, 1);
    lcd.print("for Thrice/day !");
      pushVal = 3;
      delay(500);
      break;
  }
}

// the main loop will constantly check to see if the button has been pressed
// if it has, a counter is incremented, and then some action can be taken
void loop()
{                                         //call to set thrice/day
    if (pushVal == 1) {                                // if push button 1 pressed then remind at 8am
    at8am();                                           //function to start uzzing at 8am
  }
  else if (pushVal == 2) {                             // if push button 2 pressed then remind at 8am and 8pm
    at8am();
    at8pm();                                           //function to start uzzing at 8mm
  }
  else if (pushVal == 3) {                             // if push button 3 pressed then remind at 8am and 8pm
    at8am();
    at2pm();                                            //function to start uzzing at 8mm
    at8pm();
  }
  // read the state of the button
  bS1 = digitalRead(buttonPin1);
  bS2 = digitalRead(buttonPin2);
  bS3 = digitalRead(buttonPin3);
  bS4 = digitalRead(buttonPin4);

  // check to see if it different than the last time we checked

if (bS2 != lBS2) {
    // either the button was just pressed or just released
    if (bS2 == HIGH) {
      // it was just pressed
      Serial.println("n02");
      EEPROM.write(17,1);
      push1();
      delay(1000);
    }
  }
  lBS2 = bS2;

if (bS3 != lBS3) {
    // either the button was just pressed or just released
    if (bS3 == HIGH) {
      // it was just pressed
      Serial.println("no3");
      EEPROM.write(17,2);
      push2();
      delay(1000);
    }
  }
  lBS3 = bS3;

if (bS4 != lBS4) {
    // either the button was just pressed or just released
    if (bS4 == HIGH) {
      // it was just pressed
      Serial.println("no4");
      EEPROM.write(17,3);
      push3();
      delay(1000);
    }
  }
  lBS4 = bS4;

if (bS1 != lBS1) {
    // either the button was just pressed or just released
    if (bS1 == HIGH) {
      val3=EEPROM.read(addr);
      EEPROM.write(17,0);
      digitalWrite(buzz, LOW);
      pinstop();
      EEPROM.write(17,val3);
    }
  }
  lBS1 = bS1;

  timeScreen();
  ValSet();
}
void push1() {                   // function to set reminder once/day                                           //save the state of push button-1
    lcd.clear();
    lcd.setCursor(0, 0);
    lcd.print("Reminder set ");
    lcd.setCursor(0, 1);
    lcd.print("for Once/day !");
    delay(1200);
    lcd.clear();
  }

void push2() {                      //function to set reminder twice/day
    lcd.clear();
    lcd.setCursor(0, 0);
    lcd.print("Reminder set ");
    lcd.setCursor(0, 1);
    lcd.print("for Twice/day !");
    delay(1200);
    lcd.clear();
  }

void push3() {                    //function to set reminder thrice/day
    lcd.clear();
    lcd.setCursor(0, 0);
    lcd.print("Reminder set ");
    lcd.setCursor(0, 1);
    lcd.print("for Thrice/day !");
    delay(1200);
    lcd.clear();
  }

void pinstop(){                   //function to stop buzzing when user pushes stop push button
    lcd.clear();
    lcd.setCursor(0, 0);
    lcd.print("Take Medicine  ");
    lcd.setCursor(0, 1);
    lcd.print("with Warm Water");
    delay(5000);
    lcd.clear();
  }
void at8am() {                      // function to start buzzing at 8am
  DateTime t = rtc.now();
  if (int(t.hour()) == buzz8amHH && int(t.minute()) == buzz8amMM  && (int(t.second()) == buzz8amSS || int(t.second()) < buzz8amSS+10)) {
        /////////////////////////////////////////////////////
        digitalWrite(buzz,HIGH);
        lcd.clear();
        lcd.setCursor(0, 0);
        lcd.print("Time to take ");
        lcd.setCursor(0, 1);
        lcd.print("Morning medicines.");
        delay(5000);

        /////////////////////////////////////////////////////
      }
}

void at2pm() {                          // function to start buzzing at 2pm
  DateTime t = rtc.now();
  if (int(t.hour()) == buzz2pmHH && int(t.minute()) == buzz2pmMM  && (int(t.second()) == buzz2pmSS || int(t.second()) < buzz2pmSS+10)) {
        /////////////////////////////////////////////////////
        digitalWrite(buzz,HIGH);
        lcd.clear();
        lcd.setCursor(0, 0);
        lcd.print("Time to take ");
        lcd.setCursor(0, 1);
        lcd.print("Afternoon medicines.");
        delay(5000);

        /////////////////////////////////////////////////////
      }
}

void at8pm() {                           // function to start buzzing at 8pm
DateTime t = rtc.now();
  if (int(t.hour()) == buzz8pmHH && int(t.minute()) == buzz8pmMM  && (int(t.second()) == buzz8pmSS || int(t.second()) < buzz8pmSS+10)) {
        /////////////////////////////////////////////////////
        digitalWrite(buzz,HIGH);
        lcd.clear();
        lcd.setCursor(0, 0);
        lcd.print("Time to take ");
        lcd.setCursor(0, 1);
        lcd.print("Night medicines.");
        delay(5000);

        /////////////////////////////////////////////////////
      }
}

encounters a few problems which already fixed but this one puzzles me so which problem exactly? This sketch and the complexilty of the project is huge. You should provide a minimal example of what exactly is broken with which component, then people can help you better.

the lcd and the connection to the 4 push button and is my wiring correct ?

Some troubleshooting ideas:
1. does turning the potentiometer change the brightness of the LCD?
A. If not, there is a (1) power problem (2) wiring problem.
2. Do you ever get strange characters on the LCD or just the "shows blocks instead of characters"?
A. If you only get the blocks.  THe data is probably not making it to the LCD.  THe LCD will display blocks by default.
B. If you get strange character data too, then data lines probably are't wired properly.
3. Upload a program which only does the following:
A. Initializes the LCD
B. prints one line of output every time in the loop()  This is the easiest way to determine if it is your wiring.  If you don't see anything on the LCD then there is a high probability you have a wiring problem.
This is also very easy to try because you just open up a new sketch, create it and upload it to your device.
LCD Example
Try this official Arduino LCD Example (just make sure your data lines match -- you can change the values in the sample code so they are appropriate for your situation.
If it is a wiring problem I'd start looking at

if you are getting the needed amount of current / voltage to the LCD
is each data line connected properly.  Unhook power and use a meter to check continuity from your Arduino to your LCD pins.

Your wiring image is difficult to see. I recommend checking one by one.
Firstly, you connect Arduino with LCD only, make it work first. And then try the next.
I took at a glance at your code. There are some points you should check or change:

DO NOT use delay() function, if you uses delay() function, many pressing events will be missed. You should use timestamps instead. I recommend using ezButton library to avoid the blocking or implement timestamp by yourself (refer to BlinkWithoutDelay example).
Seemingly, you are using the external pull-up/pull-down for buttons. I recommend using the internal pull-up to reduce the complexity of wiring.

For LCD, please refer to this tutorial


text:
Measure Natural Gas Pressure with arduino?
I am looking to measure Gas pressure in order to turn off Gas Heater when there is low gas. As in Pakistan alot of deaths occur when flame turns off because of low pressure of gas and then gas comes back. People suffocate into CO2. So to measure that gas what kind of sensor should i use with arduino?
Thanks

I'd probably point a light sensor toward the pilot-light (if it has one). Then sound an alarm if the light goes out. Messing with gas-lines (valves and pressure sensors) might make the whole situation more dangerous instead of safer.

Yes that also a good idea ,,

It sounds like death would be caused by gas poisoning, not CO2 (carbon dioxide) or CO (carbon monoxide) poisoning. If the flame goes out and then gas pressure is restored, un-burnt gas would be vented into the room. Unless gas is burning no CO or CO2 would be released. Further, our bodies detect excess CO2 and it causes us to feel short of breath and seek fresh air. CO on the other hand binds to the hemoglobin in our blood and prevents our blood from carrying oxygen, so we suffocate without knowing anything is wrong.
Natural gas is both poisonous and can cause explosions if it is lit with a spark. In most countries there is a scent added to the gas in the lines so we can smell it and know something is wrong. The scent is not enough to wake you up however.
The usual way to handle gas heater safety is with a pilot light and a thermocouple powered valve. The pilot light uses a tiny amount of gas to keep a small flame lit. That flame heats a thermocouple, which generates enough current to keep an electrically controlled gas valve open. If the pilot light goes out, the heat source to the thermocouple is removed, and the valve closes.
If the gas pressure drops enough, the pilot light goes out, the valve closes, and the heater turns off. If the gas pressure is restored, the user has to hold a button down to manually open the valve while re-lighting the pilot light.
In the U.S. gas heaters are required to have safety systems like I describe above. It sounds like the heaters in your country don't have safety systems like this.
Measuring gas pressure would be harder, as others have said in their answers. You'd need a sensor that is approved for use in gas appliances, as well as the fittings to attach it. The same goes for the valve that you would use to turn off the flow of gas when the pressure drops too low.
You'll need a pressure sensor approved for use with the type of gas you are dealing with, and that measures the pressure ranges in your gas lines. We can't know those things from the outside. You could probably find them out from the gas company that provides gas service.
In most countries working on gas lines and gas appliances requires special training and permits, since doing it wrong can cause explosions, fires, and gas poisoning.

Thanks man. Now i see thermocouple is used in our gas geezers and it is very effective. You are right. You gave a brilliant idea. Thanks man :)

"gas geezers"? What are gas geezers?

Gas water geezers, that are used to heat the water in cold weathers

"Water geezers" is not an idiom I've ever heard. Here in the US we just call them water heaters.

This is a fantastic idea, but you should be a bit more informed before you start the project.
I do not think the people suffocate into CO2 because CO2 is not inflammable under normal conditions so it is not used to feed the heaters. It's produced by the heater while it burns. Most probably the heater uses methane (CH4), ethane (C2H6) or propane (C3H8).
To measure the pressure, you have to insert the sensor within the gas pipe. If this is done incorrect, there is much more danger. So you have to find a fool proved method to add the sensor.
The selection of the sensor depends also on the pressure that can be considered as normal. Another value you have to find out is: how much decreases the pressure if the burner (or more burners) are switched on. i.e at which pressure do you assume the burner's flame to go out. This value must be well known.
When you know the max and min pressure values, you can look for a sensor that can safely measure this values. It should also be included in an enclosing that can be attached to the gas pipeline.
Attention: If the pressure drops just for a small moment, the flame might go off and the sensors might not be aware of that event.
Do you know, there are alternatives to measure the pressure?
A Gas Sensor in the room checks, if there is methane, ethane or propane in the air in the room. ( this is the most secure method ) There are cheap gas sensors from china, (e.g. MQ-02), but I do not know much about them. You can also combine them with a CO2 and/or CO sensors to sense whether the chimney is clogged.
A high temperature sensor near the flame recognizes if the flame is out. But this is difficult to accomplish, because you have to build the sensor into the heater.
EDIT
I want to point you to the comment of @Gerben. Checking the light of the pilot flame or the flame might also be interesting.
Having thought about this a bit,  I still find that measuring the air with gas sensors and starting a acoustic signal is the best way of doing it. If you want to close a valve in case you detect gas, the Arduino can start a siren and control the valve.
Attention: Again, working with gas installations is nothing a beginner should do. You want to save life ...


text:
Compass heading not varying linearly
I am using an HMC-5983 magnetometer compass on my arduino uno to find the heading of a car I'm building.But my compass readings aren't varying linearly.For example when I physically turn my compass by 90 degrees the change in the reading doesn't correspond to 90 degrees.I tried mapping the raw output of the compass to the actual heading but when I do this , the headings in between the points I mapped aren't accurate enough thereby causing my car to behave abnormally.I also looked up on google but couldn't find anything helpful though there was some mention about using an algorithm to sort this issue.Please help me fix this problem.
    #include <Wire.h> //I2C Arduino Library
#define Magnetometer_mX0 0x03
#define Magnetometer_mX1 0x04
#define Magnetometer_mZ0 0x05
#define Magnetometer_mZ1 0x06
#define Magnetometer_mY0 0x07
#define Magnetometer_mY1 0x08
int mX0, mX1, mX_out;
int mY0, mY1, mY_out;
int mZ0, mZ1, mZ_out;
float heading, headingDegrees, headingFiltered, declination;
float Xm,Ym,Zm;
#define Magnetometer 0x1E //I2C 7bit address of HMC5883
void setup(){
  //Initialize Serial and I2C communications
  Serial.begin(9600);
  Wire.begin();
  delay(100);

  Wire.beginTransmission(Magnetometer);
  Wire.write(0x02); // Select mode register
  Wire.write(0x00); // Continuous measurement mode
  Wire.endTransmission();
}
void loop(){

//---- X-Axis
  Wire.beginTransmission(Magnetometer); // transmit to device
  Wire.write(Magnetometer_mX1);
  Wire.endTransmission();
  Wire.requestFrom(Magnetometer,1);
    if(Wire.available()<=1)
  {
    mX0 = Wire.read();
  }
  Wire.beginTransmission(Magnetometer); // transmit to device
  Wire.write(Magnetometer_mX0);
  Wire.endTransmission();
  Wire.requestFrom(Magnetometer,1);
  if(Wire.available()<=1)
  {
    mX1 = Wire.read();
  }
  //---- Y-Axis
  Wire.beginTransmission(Magnetometer); // transmit to device
  Wire.write(Magnetometer_mY1);
  Wire.endTransmission();
  Wire.requestFrom(Magnetometer,1);
  if(Wire.available()<=1)
  {
    mY0 = Wire.read();
  }
  Wire.beginTransmission(Magnetometer); // transmit to device
  Wire.write(Magnetometer_mY0);
  Wire.endTransmission();
  Wire.requestFrom(Magnetometer,1);
  if(Wire.available()<=1)
  {
    mY1 = Wire.read();
  }

  //---- Z-Axis
  Wire.beginTransmission(Magnetometer); // transmit to device
  Wire.write(Magnetometer_mZ1);
  Wire.endTransmission();
  Wire.requestFrom(Magnetometer,1);
  if(Wire.available()<=1)
  {
    mZ0 = Wire.read();
  }
  Wire.beginTransmission(Magnetometer); // transmit to device
  Wire.write(Magnetometer_mZ0);
  Wire.endTransmission();
  Wire.requestFrom(Magnetometer,1);
  if(Wire.available()<=1)
  {
    mZ1 = Wire.read();
  }

  //---- X-Axis
  mX1=mX1<<8;
  mX_out =mX0+mX1; // Raw data
  // From the datasheet: 0.92 mG/digit
  Xm = mX_out*0.00092; // Gauss unit
  //* Earth magnetic field ranges from 0.25 to 0.65 Gauss, so these are the values that we need to get approximately.
  //---- Y-Axis
  mY1=mY1<<8;
  mY_out =mY0+mY1;
  Ym = mY_out*0.00092;
  //---- Z-Axis
  mZ1=mZ1<<8;
  mZ_out =mZ0+mZ1;
  Zm = mZ_out*0.00092;
  // ==============================
  //Calculating Heading
  heading = filtered_angle(Zm, Xm);// arc tangent of z/x

  // Correcting the heading with the declination angle depending on your location
  // You can find your declination angle at: http://www.ngdc.noaa.gov/geomag-web/
  // At my location it's 4.2 degrees => 0.073 rad
  declination = 0.03717551307 ;
  heading += declination;

  // Correcting when signs are reveresed
  if(heading <0) heading += 2*PI;
  // Correcting due to the addition of the declination angle
  if(heading > 2*PI)heading -= 2*PI;
  headingDegrees = heading * 180/PI; // The heading in Degrees unit
  // Smoothing the output angle / Low pass filter
  headingFiltered = headingDegrees;
  //Sending the heading value through the Serial Port to Processing IDE

  if(headingFiltered >= 0 && headingFiltered <= 89){
                c_head=map(headingFiltered,0,90,270,359);
        }
    if(headingFiltered > 89 && headingFiltered <= 204){
                c_head=map(headingFiltered,90,204,0,90);
        }
    if(headingFiltered > 204 && headingFiltered <= 290){
                c_head=map(headingFiltered,205,290,91,180);
        }
      if(headingFiltered > 290){
               c_head=map(headingFiltered,291,359,181,269);
        }

// Serial.print("Degrees - ");
 Serial.println(headingDegrees);
delay(500);
}

float filtered_angle(float p, float q) {
         const float filter_constant = 0.15;
         static float q_f, p_f; // filtered components
         q_f += filter_constant * (q - q_f);
         p_f += filter_constant * (p - p_f);
         return atan2(p, q);
        }

Can you give us a table with degrees, that you rotated, and the degrees, that you measured with them?

You are applying a non-linear (piecewise linear, with map()) transformation in your code. Why are you doing that? Why do you expect your non-linear transformation to yield a linear result?

If you can't find and eliminate a systemic error, such as nearby ferrous, magnetic, or electromagnetic sources, causing the errors you see, you'll need to do what navigators have done for ages: swing the compass.
Swinging a compass involves taking the vehicle - your robo-car - somewhere away from external error sources (building wiring, iron/steel masses, f/ex) and taking a set of measurements by heading the vehicle in a number of directions known by a means independent of its own compass. Eg., with a boat, you'd choose a known place in the middle of a harbor and plot a line from that known position to each landmark (for a car, you could use a large playing field). That gives you the True bearing (bearing relative to the north pole) from the chosen position to the landmark. Make a list of those landmarks and their true bearings in columns 1 & 2 of sheet of paper, in clockwise order starting a true north.
Convert the True bearings to Magnetic bearings (relative to the direction from where you are now to the earth's magnetic north pole): Navigation charts will show the difference (in degrees) between True bearings and magnetic bearings for the location(s) covered by that chart; the difference is called "variation" (sometimes called declination). If the magnetic variation at your location is westerly (compasses point 15 degrees W of True North, f/ex), add that value to those bearings you just listed. This third column of numbers is the magnetic bearing to each of those landmarks, and the value an error-free compass should read.
Now take your vehicle to that known point (playing field, middle of the harbor, etc.) and point its center line at each of those landmarks and read its compass for each one. Write these numbers in the fourth column - the compass headings to the landmarks, for this compass in this vehicle.
Columns 3 & 4 are now a compass correction table. When the compass reads a number that is in column 4 (compass bearing), the actual (corrected) magnetic heading is the corresponding number in column 3 (the magnetic headings).
But of course you don't have every possible heading in your compass correction table. So when you need to know your car's direction, you have to interpolate between a pair of bearings you do have:

Find a pair of bearings in column 4, the compass headings, that bracket the reading you just took.
Find the percentage that reading is of the difference between the bracketing compass bearings.
Apply that same percentage to the difference between the adjacent magnetic bearings in column 3 to find the actual magnetic bearing.

I glossed over the process of interpolation pretty quickly as the question was about correcting the compass. Interpolation, or other ways of applying a correction, is a whole 'nuther topic but the Arduino map() function will be great help here. Also, the more correction values (landmarks) you use to make your table, and the more evenly they are spread around the compass, the more accurate your corrections will be.

Thanks.it worked pretty well.I used the switch case control statement  and the map( )  function to get it done.


text:
Tilt Compensated Compass Using HMC5983 gives inconsistent output
I've been trying to build a tilt compensated compass for an autonomous Arduino car I'm building. I'm having issues with the consistency of my data.
This is the code I'm using.
#include <Wire.h>
#include <I2Cdev.h>
#include <MPU6050_6Axis_MotionApps_V6_12.h>
#define Magnetometer_addr 0x1E
MPU6050 mpu;

bool dmpReady = false;
uint8_t mpuIntStatus;
uint8_t devStatus;
uint16_t packetSize;
uint16_t fifoCount;
uint8_t fifoBuffer[64];
float prevoius_corrected_reading,corrected_reading;

Quaternion q;
VectorFloat gravity;
float ypr[3];

bool mpuInterrupt = false;

float Xerror = 0.01;
float Yerror = -0.385;
float Zerror = -0.17;

int X0, X1, Z0, Z1,Y0, Y1;
float X, Y, Z;
float compass_heading;

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

  Wire.beginTransmission(Magnetometer_addr);
  Wire.write(0x01);
  Wire.write(0x00);
  Wire.endTransmission();

  Wire.beginTransmission(Magnetometer_addr);
  Wire.write(0x02);
  Wire.write(0x00);
  Wire.endTransmission();

  mpu.initialize();
  //Serial.println(mpu.testConnection() ? F("MPU6050 connection successful") : F("MPU6050 connection failed"));
  devStatus = mpu.dmpInitialize();

    mpu.setXGyroOffset(51);
    mpu.setYGyroOffset(8);
    mpu.setZGyroOffset(21);
    mpu.setXAccelOffset(1150);
    mpu.setYAccelOffset(-50);
    mpu.setZAccelOffset(1060);

    if (devStatus == 0) {

        mpu.CalibrateAccel(6);
        mpu.CalibrateGyro(6);
        //Serial.println();
        mpu.PrintActiveOffsets();
        mpu.setDMPEnabled(true);
        dmpReady = true;
        packetSize = mpu.dmpGetFIFOPacketSize();
    } else {
        //Serial.print(F("DMP Initialization failed (code "));
        //Serial.print(devStatus);
        //Serial.println(F(")"));
    }

  delay(20);

}

void loop() {

  compass_heading = request_compass_data();

  Serial.print("Raw compass heading is \t");
  Serial.print(compass_heading);

  Serial.print("\t\t");

  request_accel_data();

  Serial.print("YAW\t:");
  Serial.print(ypr[0] * 180/M_PI);
  Serial.print("\tROLL\t:");
  Serial.print(ypr[1] * 180/M_PI);
  Serial.print("\tPITCH\t:");
  Serial.print(ypr[2] * 180/M_PI);

  prevoius_corrected_reading = corrected_reading;

  Serial.print("\tCorrected compass heading is \t");
  float Xhor =  X*cos(ypr[2]) + Z*sin(ypr[2]);
  float Yhor =  Y*cos(ypr[1]) - Z*sin(ypr[1])*cos(ypr[2]) + X*sin(ypr[1])*sin(ypr[2]);

  corrected_reading = rad_to_deg(rad_ang(Yhor, Xhor));
  Serial.print(corrected_reading);

  Serial.print("\tFiltered compass heading is \t");

  Serial.print(0.1 * corrected_reading + 0.9 * prevoius_corrected_reading);
  Serial.println();

}

float rad_ang(float a, float b){
  float ang = atan2(a, b);
  if(ang<0){ang += 2*PI;}
  if(ang>2*PI){ang -= 2*PI;}
  return ang;
}

float rad_to_deg(float rad_in){
  return rad_in / PI * 180;
}

float request_compass_data(){
  //return compass heading
  Wire.beginTransmission(Magnetometer_addr);
  Wire.write(0x03);
  Wire.endTransmission();
  Wire.requestFrom(Magnetometer_addr,1);
  if (Wire.available()>=1){
  X0 = Wire.read();
  }

  Wire.beginTransmission(Magnetometer_addr);
  Wire.write(0x04);
  Wire.endTransmission();
  Wire.requestFrom(Magnetometer_addr,1);
  if (Wire.available()>=1){
  X1 = Wire.read();
  }

  Wire.beginTransmission(Magnetometer_addr);
  Wire.write(0x05);
  Wire.endTransmission();
  Wire.requestFrom(Magnetometer_addr,1);
  if (Wire.available()>=1){
  Z0 = Wire.read();
  }

  Wire.beginTransmission(Magnetometer_addr);
  Wire.write(0x06);
  Wire.endTransmission();
  Wire.requestFrom(Magnetometer_addr,1);
  if (Wire.available()>=1){
  Z1 = Wire.read();
  }

  Wire.beginTransmission(Magnetometer_addr);
  Wire.write(0x07);
  Wire.endTransmission();
  Wire.requestFrom(Magnetometer_addr,1);
  if (Wire.available()>=1){
  Y0 = Wire.read();
  }

  Wire.beginTransmission(Magnetometer_addr);
  Wire.write(0x08);
  Wire.endTransmission();
  Wire.requestFrom(Magnetometer_addr,1);
  if (Wire.available()>=1){
  Y1 = Wire.read();
  }

  X0 = X0<<8;
  Z0 = Z0<<8;
  Y0 = Y0<<8;

  X = X1 + X0;
  X -= Xerror;
  Y = Y1 + Y0;
  Y -= Yerror;
  Z = Z1 + Z0;
  Z -= Zerror;

  //Calibrated manually
  X = X * 0.00092 - Xerror;
  Y = Y * 0.00092 - Yerror;
  Z = Z * 0.00092 - Zerror;
  /*
  Serial.print("XYZ\t");
  Serial.print(X);
  Serial.print("\t");
  Serial.print(Y);
  Serial.print("\t");
  Serial.println(Z);
*/
  float dir = rad_to_deg(rad_ang(Y, X));

  return dir;

}

void request_accel_data(){
        if (!dmpReady) return;
    mpuInterrupt = true;

    while (!mpuInterrupt && fifoCount < packetSize) {
        if (mpuInterrupt && fifoCount < packetSize) {
          fifoCount = mpu.getFIFOCount();
        }

    }

    mpuInterrupt = false;
    mpuIntStatus = mpu.getIntStatus();
    //Serial.print("INT STATUS:\t");
    //Serial.print(mpuIntStatus);
    fifoCount = mpu.getFIFOCount();
    //Serial.print("\tFIFO COUNT:\t");
    //Serial.print(fifoCount);

    if ((mpuIntStatus & _BV(MPU6050_INTERRUPT_FIFO_OFLOW_BIT)) || fifoCount >= 1024) {

        mpu.resetFIFO();
        fifoCount = mpu.getFIFOCount();
        Serial.println(F("FIFO overflow!"));

    }

    else if (mpuIntStatus & _BV(MPU6050_INTERRUPT_DMP_INT_BIT)) {
        while (fifoCount < packetSize) fifoCount = mpu.getFIFOCount();
        mpu.getFIFOBytes(fifoBuffer, packetSize);
        fifoCount -= packetSize;
        mpu.dmpGetQuaternion(&q, fifoBuffer);
        mpu.dmpGetGravity(&gravity, &q);
        mpu.dmpGetYawPitchRoll(ypr, &q, &gravity);
        mpu.resetFIFO();

    }
}

When I have the below sensor orientation my data output(corrected_reading) varies as shown in the below graph on one complete rotation.I'm happy with this output as there is only very little inconsistency and the tilt compensation works fine too.

However keeping them in the above orientation within my car is not practically possible in my case.
So I tried this orientation.

But no matter how I adjust my code to suit this orientation I always end up getting very inconsistent data like below.

I'm sure that there is some mistake i'm making in the second orientation i used.The biggest problem is that the raw magnetometer output(compass_heading) also becomes inconsistent in this case.
Please give me your suggestions as to what changes I should make in order to get a smooth output with the second orientation.
Thanks in advance.
Microcontroller - Arduino Uno
Magnetometer - HMC 5983
Accelerometer - MPU 6050

As it is not possible to reproduce the errors and analyse the program in detail, the thing which jumped at me that you have no gliding error correction (or its hidden in a library) for the compass (The MPU6050 has probably one as FIFO is called but you should look it up). The method is easy to explain:

You take an array of lets say 20 measure points.
You apply FIFO First value in is the last out
you do gliding average over the first 15 values -> this is the orientation output
the last 2 are used for value validation:

if you get a value out of a defined data range AND the next is in the range then ditch the before value (error corection)
if you get a value out of a defined data range AND the next 4 values are also in the range compared tothe first out of range this will cause the array to empty and start a new gliding average with these values. (Might not be the case when driving a car but in plane models this can happen -> 180 degree turns)

Its up to you how many values you take as a base reference and how many lead to an aprupt direction change. As we are in hobby electronics you can not expect high quality value delivery sowe have to use math to get to a desired result.Regarding the changed orientation of the magnetometer. EDITIn my experience the turning of the magnetometer upside down resultedin weird behavior and more unstable readings. I guess this is due to the elctronics shielding now from the top rather than the bottom.For reading and error handling I looked [into this library code]((https://github.com/keepworking/Mecha_QMC5883L/blob/master/MechaQMC5883.cpp) and adapted the read routine to my needs. Also lookat the examplesfor valuable input.

Yeah I'll try that..and the orientation is changed by 180° about the y axis in the second case I have mentioned..so how can changing x and y solve the problem?

The question is did you turn the hardware sensor 90 degree or flip upside down (there is a difference!)

I have turned it 180 degrees.Ideally the y axis will be oh the same direction it was while the z and x axes will be reversed.

See my edit and the link


text:
Using MPU6050 with ESP32 Cam- MPU Not Detected
Hi I'm trying to build a self balancing robot using my esp32 cam, but so far I haven't been able to setup my mpu6050 with it.I'm using the adafruit libraries with the given example sketches.
The only thing I've done different is using two different SDA , SCL pins. So to get that done in the software I have made the following change to the Adafruit_I2CDevice.cpp file, where the TwoWire.begin() happens.

This is the tutorial I'm following, Click Here
So Far this is What the Serial Monitor shows me
Adafruit MPU6050 test!
Failed to find MPU6050 chip

Any help to get my ESP32 to work with the MPU6050 is highly appreciated.
Also note I managed to read the bare values from the MPU using only the Wire.h library.The reson I want to use the Adafruit library is because it makes use of the DMP on the MPU6050.


text:
No programmers available for this board - Programming ESP32 Cam with Ardunio IDE
This is my first time working with ESP32 Cam boards.
I have followed the instructions as given in this site https://technoreview85.com/how-to-program-esp-32-cam-using-arduino-uno-board/
However my IDE doesn't display any programmers for this board.

Couldn't find any details about this in google. I just want to know how I could fix this problem(i.e. get the programmers listed).
Thanks in advance.

Thank you the older version of Arduino IDE. 1.8.12 also worked for me.

There are no programmers for ESP32. It only accepts Serial upload over bootloader.
Versions of IDE before 1.8.13 displayed programmers for all board support packages, that is why a programmer could be selected. Now only programmers for package of the selected board are available. But programmers are used only with the "Burn bootloader" or "Upload with programmer" commands, not with standard Serial upload over bootloader.

The older version of Arduino IDE. 1.8.12 worked.


text:
Powering ESP8266 module from arduino nano
I'm just starting up with arduino and i have few simple questions.

Why shouldn't i power ESP8266 WiFi module directly from arduino nano 3.3V rail? There are bunch of tutorials explicitly avoiding this or using resistors and i would like to know why?
Could i use something like a Mean Well Switching Power Supply, 5V 10A to power the Arduino Nano and therefore have stable voltage by avoiding batteries and by doing so, connect ESP8266 directly to arduino without fear of breaking something?
Could Arduino nano be powered through USB? And if yes, would it be then safe to connect ESP module to arduinos' 3.3V rail?

Why shouldn't i power ESP8266 WiFi module directly from arduino nano 3.3V rail?

The 3.3V rail of the Arduino is not meant to provide much current. The onboard regulator is a simple linear voltage regulator, which will dissipate the extra power as heat. As you draw more current through it, it will get hotter and finally get fried, as it cannot dissipate the created heat. The ESP chip needs multiple hundreds of mA, especially, when it is connecting to a wifi network. The onboard voltage regulator of the Arduino cannot handle this much. So you cannot power it over the Arduino.
I don't really know, what you mean with "using resistors".

Could i use something like a Mean Well Switching Power Supply, 5V 10A to power the Arduino Nano [...] connect ESP8266 directly to arduino without fear of breaking something?

Yes, you can power the Arduino with this power supply, but you should power the ESP through the Arduino. Not through the 3.3V, nor through the 5V rail (which will fry the protection diode, I think). Instead you should power the ESP directly from the power supply, in parallel to the Arduino. Often ESP modules have their own voltage regulator, that regulates the voltage from 5V to 3.3V. If that is the case for you, you should use this input of the ESP module with the power supply. If you don't have a 5V capable regulated input on your ESP module, you will have to use a dedicated voltage regulator for that. In that case be sure, that the voltage regulator can provide enough power for the ESP (with some headroom on top).

Could Arduino nano be powered through USB? And if yes, would it be then safe to connect ESP module to arduinos' 3.3V rail?

Yes, the Arduino Nano can be powered over USB. But again you must be sure to not draw too much current from the Arduino. Between USB and the 5V rail is a diode, that will be destroyed, if you draw too much current through it. And the standard USB port can only provide up to 500mA. And regarding the 3.3V rail: All the explanations above about the 3.3V rail apply here again, since the USB voltage (5V) is regulated down to 3.3V by the linear voltage regulator. So: No, you still cannot power the ESP through the Arduino. It's not about the power supply here, but about the electronic parts inbetween.

Thank you, that clears it up a lot !

part. esp8266 has max 170 mA draw. the 3.3 V regulator on standard Uno can supply 150 mA so it usually works. on Nano the 3.3 V si from the FTDI USB chip (50 mA?) 2. dev boards have regulators. modules do not


text:
Powering two stepper motors with A4988 drivers
New to this site and wanted advice and sanity checking on my project design. I know there are similar questions to this but I couldn’t find one that was closely similar to mine.
I’m creating a device the uses two NEMA 17 stepper motors (https://www.omc-stepperonline.com/nema-17-stepper-motor-bipolar-l48mm-w-gear-raio-1001-planetary-gearbox-17hs19-1684s-pg100.html) with chunky 100:1 gearboxes in addition to using 1/16 microstepping. The end result of this is to achieve a stepper motor that turns very slowly (minutes per revolution).
Each motor is rated at 2.8V and 1.68A per phase (3.36A total since two phase) and I’m using an A4988 driver for each of them (https://www.amazon.co.uk/gp/product/B07FKXXJ41/ref=ppx_yo_dt_b_asin_title_o00_s00?ie=UTF8&psc=1) (note that these are Chinese versions where RCS = 0.1Ω). Since the A4988 drivers are limited to 1A without additional cooling, I’ve used the onboard potentiometer to reduce Vref to just below 0.9V to prevent overheating (using the equation Vref = 8 x Imax x RCS from Pololu).
This should mean that consequentially the torque output from each motor is reduced by a factor of 1/(3.36) = 0.3 (as torque α current) since each motor is only being supplied with 1A (which is not an issue due to the large gearing ratio giving a suitable output torque). I think 1/16th microstepping might also reduce the torque slightly, but I couldn’t find any conclusive sources that didn’t contradict each other on this.
This gives a power requirement of 2.8 x 1 = 2.8W per motor, hence 5.6W in total. So, I plan to use a power source that provides at least 3A (surplus on the 2A required by the drivers) and rated at a voltage of 12V-24V to run the stepper motors. I’m also aware that I need to make sure I power the drivers in parallel from this source, and not in series to reduce strain / overheating.
I’ve included two power sources I was thinking of using:
1: 24V, 4A, 96W Desktop Switching Power Supply (https://www.amazon.co.uk/DTK-Charger-90-240V-Switching-Transformers/dp/B07K85GJ54/ref=sr_1_1_sspa?crid=362Z7XFFLAYLL&keywords=24v+3a+dc+power+supply&qid=1565084176&s=electronics&sprefix=24V+3A+dC%2Celectronics%2C124&sr=1-1-spons&psc=1&spLa=ZW5jcnlwdGVkUXVhbGlmaWVyPUFHM1hUTjRTOUhYVDcmZW5jcnlwdGVkSWQ9QTA5NzA5MzQzM09IT05IR1JITEpQJmVuY3J5cHRlZEFkSWQ9QTA0NjgyMTUyQjY0UEYzRFI5OVBFJndpZGdldE5hbWU9c3BfYXRmJmFjdGlvbj1jbGlja1JlZGlyZWN0JmRvTm90TG9nQ2xpY2s9dHJ1ZQ==)
2: 24V, 15A, 360W PSU Transformer Adaptor (https://www.amazon.co.uk/NEWSTYLE-Universal-Regulated-Switching-Transformer/dp/B0758BNMLH/ref=sr_1_3?keywords=PSU+24V&qid=1565084433&s=electronics&sr=1-3)
Overall question is: would either of these power supplies be suitable, I think the second might be a bit overkill but i'm not sure.
Here’s the circuit diagram for reference:

Apologies for the long post, just needed to get all the information out of my head. I’m curious to see if I’ve made any errors in my calculations / assumptions, so any help is greatly appreciated.

Both power supplies are suitable.
The actual 12V/24V current required is not comparable to what the driver current is set at, since the stepper motor coils do not have those 12V/24V across them.
My first 3D printer came with a 12V 5A power supply, which proved suitable for simultaneous use of four stepper drivers, the control board, a display, and the heater cartridge (40W).

The 5A PSU might be a little under powered, since there might be a significant torque on the motors due to the gearboxes being so lowly geared, causing the windings to need more amps to move the shaft. However, since there's not likely to be any major/sudden speed changes with this setup, it should be minimal. Over driving a PSU can lead to premature failure, so getting a higher rated one is recommended. The price difference in negligible either way. I'd suggest testing to see what amps are actually pulled before buying anything.


text:
I´m trying to make a kind of videogame with Arduino UNO
it´s a school project, but I'm having some problems to create a menu selection. In the LCD, all the character are overwriting, I'm a beginer, so i dont have any idea of what i was doing wrong (ps.: sorry about my english, i'm a brazilian.
Here goes the code:
//A portable "atari" videogame project, including 3 games
#include <LiquidCrystal.h>
//define os pinos a ser utilizados no arduino uno,etc.
#define btcima 9
#define btbaixo 8
#define bttiro 10
#define menu 11

LiquidCrystal lcd(7,6,5,4,3,2);

int vel=100;
 int pxnave,pynave,pxaste,pyaste,pxtiro,pytiro;//px=posição x, py=posição y, etc
bool game1,game2,game3,vtiro;//vtiro=variavel de tiro
int pontos;
int maxpontos=15;
int vtela;
byte nave[8]={B00000,B01100,B00110,B11111,B00110,B01100,B00000,B00000};
byte asteroide[8]={B01110,B10111,B11111,B11101,B10111,B01110,B00000,B00000};
byte explosao[8]={B10101,B00010,B11000,B10101,B01010,B10110,B01101,B10011};
byte tiro3[8]={B00000,B00000,B11110,B11111,B11111,B11110,B00000,B00000};

int      line[4] = {0,1,2,3},
         line_bk[4],
         index,
         menu_number = 0;

boolean  menu_flag  = 0,
         enter_flag = 0,
         sub_menu = 0;

void readButts();
void list_menu();
void menu_select();

void setup()
{
  //--configuração do menu--
 pinMode(menu,  INPUT_PULLUP);
  pinMode(bttiro, INPUT_PULLUP);

 lcd.begin (16,4);
 //lcd.setBacklight(HIGH);--apenas para lcd i2c
 lcd.clear();
 lcd.setCursor(0,0);
 lcd.print(">");

pxnave=pynave=pyaste=pontos=pytiro=0;
pxtiro=-1;
pxaste=12;
vtela=0;
lcd.createChar(1,nave);
lcd.createChar(2,asteroide);
lcd.createChar(4,explosao);
lcd.createChar(6,tiro3);
//lcd.begin(16,2);
//lcd.clear();
game1=-false;
game2=false;
game3=false;
vtiro=false;
}

void loop(){

  if(!sub_menu)
  {
   lcd.clear();
    lcd.setCursor(1,line[0]);
    lcd.print("1) NAVE: THE GaMe       ");
    lcd.setCursor(1,line[1]);
    lcd.print("2) PING PONG       ");
    lcd.setCursor(1,line[2]);
    lcd.print("3) lula & dilma      ");
    lcd.setCursor(1,line[3]);
    lcd.print("4) Creditos     ");

  }

  readButts();

  if(game1){
    lcd.clear();
    vtela=0;

  if (digitalRead(btcima)==1){
    pynave=0;

  }
  if(digitalRead(btbaixo)==1){
    pynave=1;
  }
  if(digitalRead(bttiro)==1){
    pxtiro=1;
    vtiro=true;
pytiro=pynave;
  }
  pxaste-=1;
  desenhaNave(pxnave, pynave);
  desenhaAsteroide(pxaste, pyaste);
  if(vtiro){
    desenhaTiro3(pxtiro, pytiro);
    pxtiro+=1;
  }

  if(pxaste<0){
  pxaste=12;
  pyaste=random(0,2);
  }
  if(pxtiro>16){
    vtiro=false;
    pxtiro-=1;
  }
  if (((pxtiro==pxaste+1)&&(pytiro==pyaste))||((pxtiro==pxaste)&&(pytiro==pyaste))){
  vtiro=false;
  pxtiro=-1;
  desenhaExplosaoAsteroide(pxaste, pyaste);
  pyaste=random(0,2);
  pxaste=12;
  pontos+=5;
  if((pontos>=maxpontos)){
    game1=0;
    vtela=7;//rever
  }
}
if((pxnave==pxaste)&&(pynave==pyaste)){
game1=0;
desenhaExplosaoNave(pxnave, pynave);
vtela=6;
}

  delay(vel);

  }else{
    tela(vtela);
    if(digitalRead(bttiro)==1){
      reset1();
    }
  }
}

  void readButts()
{

   if(!digitalRead(menu))  menu_flag  = 0x01;
   if(!digitalRead(bttiro)) enter_flag = 0x01;

   if(digitalRead(menu) && menu_flag)
   {
       menu_flag = 0x00;
       list_menu();
       menu_number+=1;
       if(menu_number > 5) menu_number = 1;

   }

   if(digitalRead(bttiro) && enter_flag)
   {
      enter_flag = 0x00;
      sub_menu = !sub_menu;
      menu_select();

   }

}

void list_menu()
{
  for(int i=4; i>-1; i--)
  {
     index = i-1;
     line_bk[i] = line[i];

     if(index < 1) line[i] = line_bk[i+4];

     else line[i] = line[i-1];

  }

}

void menu_select()
{

    switch(menu_number)
    {
       case 1:
        vtela==0;
        game1= true;
        game2=false;
        game3=false;

               break;
       case 2:
            vtela==4;
              game1= false;
        game2=true;
        game3=false;
               break;
       case 3:
           vtela==5;
           game1= false;
        game2=false;
        game3=true;
               break;
       case 4:
               vtela==8;
               game1= false;
        game2=false;
        game3=false;
               break;
       //case 5: ---pensar---

    } //end switch

}
  void desenhaNave(int px, int py){
  lcd.setCursor(px,py);
  lcd.write(1);
}
void desenhaAsteroide(int px, int py){
  lcd.setCursor(px,py);
  lcd.write(2);
}

void desenhaTiro3(int px, int py){
  lcd.setCursor(px,py);
  lcd.write(6);
}
void desenhaExplosaoNave(int px, int py){
 lcd.clear();
  lcd.setCursor(px,py);
  lcd.write(4);
  delay(1000);
  lcd.clear();
}
void desenhaExplosaoAsteroide(int px, int py){
  lcd.setCursor(px,py);
  lcd.write(4);
  delay(1000);
  lcd.clear();
}
void reset1(){
  pontos=0;
  game1=true;
  vtela=0;
}
void reset2(){
  pontos=0;
  game2=true;
  vtela=0;
}
void reset3(){
  pontos=0;
  game3=true;
  vtela=0;
}

void tela(int cond){//0=jogo da nave 1=ganhou 2= perdeu 3= menu de seleção 4=jogo pingpong 5=jogo plataforma

if(cond<1){
   lcd.setCursor(3,0);
     lcd.print("Nave: THE GAmE");
     lcd.setCursor(0,1);
lcd.print("PRESSIONE START");
}
if(cond==6){
  lcd.setCursor(9,0);
  lcd.print("pts:");
  lcd.setCursor(13,0);
  lcd.print (pontos);
  lcd.setCursor(1,0);
  lcd.print("Perdeu");
lcd.setCursor(0,1);
lcd.print("PRESSIONE START");
}
if(cond==7){
  lcd.setCursor(9,0);
  lcd.print("pts:");
  lcd.setCursor(13,0);
  lcd.print (pontos);
  lcd.setCursor(1,0);
  lcd.print("Ganhou");
lcd.setCursor(0,1);
lcd.print("PRESSIONE START");
}
if (cond==3){
  sub_menu=true;
  lcd.clear();
}

if(cond==4)
{
  lcd.setCursor(3,0);
  lcd.print ("Ping Pong");
  lcd.setCursor(0,1);
  lcd.print ("PRESSIONE START");

}
if (cond==5)
{
  lcd.setCursor(3,0);
  lcd.print("Lula e Dilma");
  lcd.setCursor (0,1);
  lcd.print ("PRESSIONE START");
}
if (cond==8)
{
  lcd.setCursor(3,0);
  lcd.print("Equipe LULA Livre");
  lcd.setCursor(0,1);
  lcd.print("Obrigado por Jogar");
}
}`enter code here`

Just for inspiration, you may want to take a look at Arduboy and the open source libraries its games are built on.

https://wokwi.com/arduino/projects/297467237377245705 can you check this link

Probably since you set the cursor at a position in the middle of a line, only the new text is overwritten over the old text. But if there are some characters from the previous text, those will stay.
So the easiest way is to either clear the screen (if you can do the updating of the screen from a single place), or rewrite the entire line (and probably having to add spaces before/after the text you want to write to overwrite the old text).
Some other tips:

Write comments and variable names in English (I know it's not your mother
language, but you can learn two languages at once, C and English).
Align your code (make sure each { and } is aligned nicely; this will make life much easier and prevent mistakes.
game1, game2 and game3 are booleans where only one can be true. For this the enum (enumeration) is invented. So make an enum enum Game { game1, game2, game3 }; as a type, and declare a variable Game currentGame = game1;
You use a switch statement for menu_number, but why not for cond?
You use a lot of text, all text also takes up precious SRAM, where you only have 2,048 bytes of. If for each string you add F in front (thus e.g. F("MENU"); this will be stored only in Flash.


text:
Checking Specific Brand SIM card Type Available in GSM module
Can I program a GSM module to accept a specific type of Sim card to be ready by the module? If so please post something that can give me an Idea of how do it. Generally I want to lock the GSM module to accept a given brand of sim card to be detected in the Module but I do not know if its possible. I will be glad for any help offered by anyone on the platform. I will be glad for any help

write the software to work only with certain SIM cards

How can I do that? maybe provide a link were I could get some insight on how its supposed to be done


text:
5 minute timer output time remaining
I am trying to create a timer that outputs the time remaining in minutes. I am using an Adafruit Circuit Playground Express.
For example, if the timer is 5 minutes, then every minute it should output the time remaining, until the time ends.
5 minutes timer started.
Delay: 5 minutes
Delay: 4 minutes
Delay: 3 minutes
Delay: 2 minutes
Delay: 1 minute
This is my attempt to implement this. I would like it to start by displaying  "Delay: 5 minutes"; however, this is not output until 1 minute has passed.
What am I doing incorrectly?
const long interval = 1 * 60 * 1000UL;
unsigned long previousMillis = 0;
int minutes = 5 ;

 unsigned long currentMillis = millis();

  while (minutes >= 0){
  if (currentMillis - previousMillis >= interval) {
    // save the last time you blinked the LED
    previousMillis = currentMillis;

    Serial.print(F("Delay: "));
    Serial.print(minutes);
    Serial.println(F(" minute(s)"));
    minutes = minutes - 1;
  }
  }

it does not output the correct remaining time is not a useful description of the output .... it would be much more useful if you say what the output actually is

Also, h ow is previousMillis defined and initialized?

Same question was asked and is being discussed here  https://forum.arduino.cc/index.php?topic=632900.msg4285177#msg4285177

why are you posting your question here? ... the Arduino forum is giving you good suggestions

Try this: (I don't have an Arduino here so i can't test it)
int minutes = 5;
int passedminutes = 0;
void setup() {
 Serial.begin(9600);
}
void loop() {
  while((millis() - minutes*60000) < 0)
  {
    if(millis()%60000 == 0)
    {
      Serial.print("Remaining Time: ");
      Serial.println(minutes-passedminutes);
      Serial.println();
      passedminutes++;
      delay(1);
    }
  }
}

millis()%60000 is fragile, because the millis() counter skips some values. Roughly one every 42 values.


text:
Not Able to get INPUT_PULLUP pinmodes to work on multiple pins
I am working with an Arduino nano, and ic2 128x32 OLED display and a 1x4 membrane keypad. Problem is that only one of the 4 pins are detecting the button press. it's not the Arduino, I already was able to reproduce the same issue on another one. the keypad is also working fine, as I have tested it. (edit now only pin 9 is working)
#define b1 6
#define b2 7
#define b3 8
#define b4 9

// in setup

pinMode(b1, INPUT_PULLUP);
pinMode(b2, INPUT_PULLUP);
pinMode(b3, INPUT_PULLUP);
pinMode(b4, INPUT_PULLUP);

// in loop

int b1S = digitalRead(b1);
  int b2S = digitalRead(b2);
  int b3S = digitalRead(b3);
  int b4S = digitalRead(b4);

  if(!b1S){
    Serial.println("Button 1");
    }

  if(!b2S){
    Serial.println("Button 2");
    }

  if(!b3S){
    Serial.println("Button 3");
    }

  if(!b4S){
    Serial.println("Button 4");
    }

Please help! Thanks

How is everything connected? Have you measured, if there is 5V on the specified pins, when you don't press a button? Also measure without the keypad

to answer how its connected, each pin defined in the code is connected to one of the inputs of the buttons on the keypad with it all connected to a common ground

and b2 and b4 are giving around 4v and the other 2 are giving readings somewhere in the millivolts, that's not right, right?

I'd suggest backing up and testing each part separately. Get a breadboard and a momentary switch. Connect the switch through to ground on one pin at a time. See if a test sketch is able to detect the change in state for each pin when it's configured as INPUT_PULLUP. If not, try using INPUT, and attaching the pin to +5V through a 10kΩ resistor.  Also use an ohm-meter to verify that your membrane switches are open unless pressed, and connect to ground when they are pressed.

Have you measured these voltages with connected keypad? If yes, try without the keypad - just the bare arduino. If the voltages are still that low, the Arduino is probably broken.


text:
Slow USB reading operation
I got an Arduino UNO today, and I am just writing a basic blink program. I have 3 LEDS on the arduino. Those LEDS are connected to Pin 1, 2, and 3.
Now I can control those LED by writing octal values 0 to 7 to the /dev/ttyUSB0.
The code I have written so far is:
# pragma GCC optimize ("Ofast")

# define LED1 1
# define LED2 2
# define LED3 3

char buf[4] ;
unsigned char inp, len ;

void setup() {
    pinMode(LED1, OUTPUT) ;
    pinMode(LED2, OUTPUT) ;
    pinMode(LED3, OUTPUT) ;

    Serial.begin(9600) ;
}

void loop() {
    len = Serial.readBytes(buf, 3) ;

    if (len) {
        buf[3] = '\0' ;
        inp = atoi(buf) ;

        // Illuminate LEDs
        digitalWrite(LED1, 1 & inp ? HIGH : LOW) ;
        digitalWrite(LED2, 2 & inp ? HIGH : LOW) ;
        digitalWrite(LED3, 4 & inp ? HIGH : LOW) ;
    }
}

So when I write:

0 turns off all the LEDS
1 turns on LED on pin 1
2 turns on LED on pin 2
3 turns on LED on pin 1 and 2
4 turns on LED on pin 3
5 turns on LED on pin 1 and 3
6 turns on LED on pin 2 and 3
7 turns on all the LEDS.

The problem is that, when I write 7 for example, it takes up to 1 second to turn on the LEDS. If I write 0, it takes another second to turn off the LEDS.
Is there way to control the LEDS in close to real-time?

When sending multiple bytes which together form a single message it is best to use a delimiter character and read the data until there. That way you don't run into timeouts and you can be sure, that the received data represents a full message.
In the cases where the LEDs need 1s to react you are most likely sending less than 3 bytes, which causes the Serial.readBytes() function to time out after the default 1s. I guess you are currently always sending only 1 byte (though you are trying to read 3 byte in your code).
To use a delimiter character there are multiple ways. The easiest fix would be using Serial.readStringUntil('\n'). The newline character (which I used as a parameter here) is a common delimiter character. You would then need to aways send the newline character at the end of a full message.
Just setting the timeout very low is not a very good solution. With a low baudrate as 9600 that can easily mean, that the message is chopped up into multiple parts, because the transmission takes longer than the timeout.

Besides that: I don't really understand, why you need to receive 3 bytes for turning on or off 3 LEDs. One byte (even, when you are just using single digits) has a big enough data space for more than these 3 LEDs. Also you are not really using octal numbers. atoi() is expecting a string representation of a decimal number. There is nothing octal in your code. And then you are using the first 3 bits of the resulting number for controlling the LEDs.
All in all this seems quite complicated for a very basic task. Maybe there is some reason for that, which you didn't write about.

You're calling Serial.readBytes() when there may or may not be 3 bytes available. If there aren't 3, the call waits for them to arrive or for a timeout. That's the delay you are seeing.
If you really want 3 bytes at a time, check whether there are 3 before you try to read them:
if( Serial.available >= 3 )
   len = Serial.readBytes(buf, 3);

When the if fails - because there aren't three bytes available - you won't waste any time waiting for them.

On the Arduino UNO pins 0 and 1 are used for serial communications.  That might not make a difference here, but it's probably a good idea to avoid them unless really needed.

This should be a comment


text:
How do I set a constant in setup() that I can use in loop()?
I am new with coding, and I was wondering how I could run something once and define it as a constant. Here is my code:
int sensorValue1 = analogRead(A0);
int sensorValue2 = analogRead(A1);
int g0 = 9.81*9.8;
int h1 = 48;
int R = 287.06;
int a = -0.0065;

void setup() {
    Serial.begin(9600);
    int p1 = (1.09512*sensorValue2-22.105)*133.3225;
    int t1 = (-0.08126*sensorValue1+65.6597)*274.15;
}

void loop() {
    String t = "Temperature:    ";
    String tt = " Celsius";
    String p = "Preassure:    ";
    String pp = " Pascal";
    float celsius = -0.08126*sensorValue1+65.6597;
    float kelvin = celsius*274.15;
    float pascal = (1.09512*sensorValue2-22.105)*133.3225;
    float height = (t1/a)*((pascal/p1)^((a*R)/g0))-1)+h1;
    Serial.println(t+celsius+tt);
    Serial.println(p+pascal+pp);
    Serial.println(kelvin);
    Serial.println( );
    Serial.println(height);
    delay(1000);
}

What do you need to run something once? Put in inside "setup" method (it gets executed once the Arduino powers up or gets reset)

You can't, and there's other things wrong with your code.
int sensorValue1 = analogRead(A0);
int sensorValue2 = analogRead(A1);

Calling functions from the global scope is an incredibly bad idea.  Those are run before the board has been properly initialized, and the results you may get from it are not guaranteed in any way, shape, or form.  Instead you must call functions like analogRead() from within another function, like setup(), or loop().
As for const - a const is just that - a constant value that can never change.  You can only assign a value to it at the moment of creation.
And that means that you can only use it within the scope it was defined within.  As you can't do that in the global scope (see above) then you cannot use a constant.
So just use a normal global variable.  It will only change when you tell it to change.  Using a const only makes sense when you have a numeric literal that you want to refer to by name. Using const doesn't protect the variable from being changed at run-time by memory leaks, etc, it just protects it from attempts to modify it at compile time - and if possible replace it with the numeric literal that it refers to.
So in summary just use:
int sensorValue1;
int sensorValue2;
int p1;
int t1;

void setup() {
    sensorValue1 = analogRead(A0);
    sensorValue2 = analogRead(A1);
    p1 = (1.09512*sensorValue2-22.105)*133.3225;
    t1 = (-0.08126*sensorValue1+65.6597)*274.15;
}
... etc ...

HOWEVER: Your program methodology is also completely flawed.  You read the analog values once, and do calculations with them once, then repeatedly display the same values over and over again.
You must perform a new analogRead() of your sensors every iteration of loop() in order to update the values in your variables.

You can define Constants using the "const" keyword. Ex:
    const float pi = 3.14;
    const int foo = 12;

https://www.arduino.cc/en/Reference/Const

However scope rules mean that variables declared in setup() won't be visible in loop() – to make them visible declare them outside of any function.

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


text:
nRF24L01+ packet loss caused by Arduino reading and communicating with sensors
I have 2 Arduinos communicating with each other. My problem is that one sends packets every 1.5-2 seconds but the other Arduino does sensor reading and data uploading with a Wifi module, which may take up to 5 seconds until the next time the nRF24L01+ is available to receive data.
This results in about 4 packet losses and if I am lucky sometimes 2. Is there any way that when the nRF24L01+ sends data, the other Arduino stops everything to get the data? Like a communication between these two Arduinos that will be open 24/7, so that the other Arduino can multitask (reading sensors and upload the data through wifi).
I am using the code from this tutorial. Here is a my problem in an image (I hope this helps you understand it). Thanks in advance.

Are you using software serial for WiFi module?

Yes and I am communicating using AT commands.

The NRF24L01 has a RX FIFO buffer of 3 packets. So I don't see how you could miss 4 packets. My guess is that something else is going wrong. Could you post some minimal code that still produces that error.

It's not clear right now if the reason you are missing packets is because you are operating the wifi in a blocking way, or if it is because the wifi radio is interfering with the nRF24 one in the same general frequency range.  Both are potential issues.   Could you have your nodes number each reading and send it at multiple points in time?  So a given transmission might include readings 1345, 1346, and 1347 while the next transmission would have 1346, 1347 and 1348, etc.

I see this is an old thread, but thought I'd chime in.
For an example implementation of a finite state machine, there are libraries built for this or you can use simple loop timers with if statements to "poll" sections of code instead of using ANY delays. Delays stop execution and waste your MCU time, preventing it from doing anything else, as already mentioned. Checking for wifi or serial messages can then execute with higher priority. An example pseudo-code would look like:
int update_ms = 500;
int last_update_ms;

setup{

last_update_ms = millis(); // or 0, to execute immediately

}

loop{

if(millis() - last_update_ms >= update_ms){
    last_update_ms = millis();
    execute_thing();}

check_for_wifi_msg();

}

There are libraries that do this essential behavior for you with more eloquence, as well, such as PollingTimer. I'm often surprised this isn't given as tool early on when people learn Arduino/ MCU programming, or in example codes. It is easy and so powerful.
You could accomplish the same "finite state machine" functionality with a real-time operating system built for microcontrollers. I can recommend FreeRTOS as a user-friendly entry to this. This makes your single core machine work like a multi-core machine, with a task scheduler. You can define several continually running while loops that the RTOS thread handler then interleaves for consistent execution. You could have 1 thread for your RF and 1 thread for your WiFi, with set execution rates, and RTOS handles the rest, e.g. it will try to fit RF reads inside of the Wifi loop whenever it can find downtime. This will likely make your Wifi loop somewhat longer as a sacrifice.
You can get started with these:
FreeRTOS Kernel Quick Start Guide
The FreeRTOS Reference Manual
Other solutions, which I won't elaborate on here include using a multi-core chip, like a ESP32, or to make use of WiFi interrupts to break out of other execution. Though, I do not know if this is specifically supported on the nRF24L01+.

You need to re-factor your program somewhat (I would imagine).  The nRF needs to be read at the same time as doing other things. That means interleaving it with your other operations.
There is a concept called a finite state machine which is the best way of writing a complex program like this. The idea is that nothing ever blocks, it just changes states. And all the time other things can be happening, such as reading the nRF24L01+ module.
I have a little tutorial on the Finite State Machine here:

https://hackingmajenkoblog.wordpress.com/2016/02/01/the-finite-state-machine/

If you use the Finite State Machine concept to run the reading of your sensors and the writing of data to the WiFi the nRF can then be polled constantly outside of the FSM constantly - maybe with an FSM of its own to deal with reception etc.
Things to remember:

Avoid delay(), certainly for anything longer than a couple of ms.
Avoid while(), for(), etc except for very short loops that finish quickly.
Any operation that takes more than a few ms to complete should be broken down into a number of sub-operations and coded as separate states of the FSM.

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


text:
How to send data from ThingSpeak to ESP-8266 (Arduino) using ThingHTTP?
I have made an Arduino kit that acts as a weather station. It sends sensors data (DHT11 & LDR) to the ThingSpeak web server.
Now I want to perform some actions based on the data on the ThingSpeak server (like if temperature exceeds a limit turn on the fan, etc).
I've searched and I found that there's a React app on ThingSpeak, which will trigger events if data exceeds some values.
The problem where I got stuck is that I want to send a signal from the ThingSpeak web server to my ESP8266 (Arduino) to turn on/off the device connected to a relay on Arduino.
I've figured out that there's also a ThingHTTP feature which sends HTTP requests. But I don't know how to send requests/signals to my kit to perform some actions.
I've already spent 2 months building this project, and now I'm stuck in the last part. Please give your valuable suggestions and solutions.

Why do you think you need to bounce the value via ThingSpeak when the Arduino already knows what is going on, since it has send those values to ThingSpeak in the first place?

You raised a valid point! Yes we can burn such code which will perform action according to the sending values but It'll be considered as hard coding and will result into more problems !! Because we've 110 nodes (Arduino kits) and suppose for some reason we've to change the threshold of temperature data for performing some relevant action, then we'll have to burn the modified code again to all the 110 kits. We are thinking to control all these devices from 1 place ( web app). Thanks for your response. Looking forward for your suggestion.

That makes perfect sense.


text:
Not Receiving HC-05 data
I've been trying to use this HC-05 bluetooth module for a project, where the data would be sent to a Max/MSP/jitter program. Initially, every time I connected my bluetooth device to my computer, it stayed connected for about 10 to 20 seconds then disconnect. I'm not sure if it's a voltage thing, but from what I read on other forums, it should work fine. My setup:
1- Powering Arduino on a wall wart (Input: 100-240V AC, 50/60Hz 0.3A ; Output: 12V DC 1A);
2- Bluetooth's Tx to Arduino's Rx (D3) and Bluetooth's Rx to Arduino's Tx (D4)
3- APDS9960 sensor also connected on the same breadboard (the sensor I should be receiving the data from, and I do, when connected on an USB cable port)
4 - HC-05 configured to be 115200 baud (AT+UART=115200,0,0), which seems to be the appropriate bps for HC-05 to Max (??)
But then... Once I logged into Max, and printed the data from this serial port (which should send data in a continuous fashion), some lines were printed and then it stopped. So I go on to check the Arduino Serial Monitor and – though everything seemed to be working fine and I received the data properly – there's nothing showing up.
#include "SoftwareSerial.h"
#include <Arduino_APDS9960.h>

SoftwareSerial blue(3,4); //rx tx, qualquer 2 portas digitais sem ser 7 e 8

void setup() {
  // put your setup code here, to run once:
 Serial.begin(115200);
 blue.begin(115200);

  Serial.println("mensagem do computador");
  blue.println("mensagem do módulo bluetooth");

   if (!APDS.begin()) {
    blue.println("Error initializing APDS9960 sensor.");
  }
}

void loop() {
  // put your main code here, to run repeatedly:

    while (! APDS.colorAvailable()) {
    delay(5);
  }
  int r, g, b;

  // read the color
  APDS.readColor(r, g, b);

  // print the values
//  blue.print("r = ");
  blue.println(r);
//  blue.print("g = ");
  blue.println(g);
//  blue.print("b = ");
  blue.println(b);
//  blue.print();

  // wait a bit before reading again
  delay(100);
}


text:
How to Burn Bootloader with custom Fuses
I have a Atmega328p IC without external Crystal (My target).
When I use a arduino to burn the bootloader to my target, the Arduino as ISP sketch changes the fuses of my target, so it tries to use its external crystal, which is not connected, So it cannot proceed the bootloader burn.

How can I modify the Fuse settings while Burning bootloader with arduino?

You need to either adjust the current board fuse settings in boards.txt or create a new board variant that matches your settings.
For example the Uno is set up with:
uno.bootloader.tool=avrdude
uno.bootloader.low_fuses=0xFF
uno.bootloader.high_fuses=0xDE
uno.bootloader.extended_fuses=0xFD
uno.bootloader.unlock_bits=0x3F
uno.bootloader.lock_bits=0x0F
uno.bootloader.file=optiboot/optiboot_atmega328.hex

and after changing this file, I needed to re-start the arduino.exe, thank you!

You can use MiniCore boards support package for Arduino IDE to work with nonstandard AVR boards or breadboard setups. This core has many settings in Tools menu to set different parameters of the board.