body:
For a small project, I aim to connect a **digital temperature sensor (KY-028)**, a **Bluetooth module (HC-05)** and a **servomotor (SG90)**. The problem is it seems I can't connect the Bluetooth module and the servomotor together at the same time. The Bluetooth module together with the temperature sensor works fine. The servo with the sensor, again, all fine. But it seems these two don't agree with each other: as soon as I upload the code on the board **(Arduino UNO)**, the servo starts vibrating (not even rotating), altough I made sure no command that asks it to do so is reached. Also while doing this, the Bluetooth module's led is turned off and it is unrecognizable by other devices.

When I upload the program to the board, I disconnect the RX and TX pins of the Bluetooth module from the pins 0 & 1 of the Arduino board, (otherwise I get errors and the program is not uploaded - if needed, I will get the error codes I get and edit the post), but after upload, the servo starts behaving weird, as described before. As I read on another article (if I manage to find the link again I will post it here), it might behave like this because there are unconnected pins in my whole circuit (which is true, but otherwise I can't connect the Bluetooth module). How could I possibly connect both of them on the same board?

I tested the code segments, they act as they should, I tried switching the pins so that I did not miss anything by mistake, as I am a total beginner (for instance I tried putting the signal wire of the servo on both PWM and not PWM supporting pins, tried connecting the Bluetooth module and the servo to different grounds etc.) but no success.

Any help would be much appreciated. If the layout of my circuit is needed, I will try to make one in a simulator. Thank you very much!

**Edit**

Here is the code:

    #include <Servo.h>
    #include <SoftwareSerial.h>

    int txPin = 1;
    int rxPin = 0;
    int digitalPin = 7; // KY-028 digital interface
    int analogPin = A2; // KY-028 analog interface
    int angle = 0;
    int temp;
    bool incTemp = false, decTemp = false;

    Servo servo;
    SoftwareSerial BT(txPin,rxPin);

    void setup() {
      pinMode(digitalPin, INPUT);
      pinMode(analogPin, INPUT);

      servo.attach(11);
      delay(100);

      BT.begin(9600);
      Serial.begin(9600);
    }

    void loop() {
      temp = analogRead(analogPin);
      Serial.println(temp);

      if (BT.available())
      {
        char bytesToSend[2];
        bytesToSend[0] = 101;
        bytesToSend[1] = temp;
        bytesToSend[2] = 110;
        BT.println(bytesToSend);
      }

      if(incTemp)
      {
        servo.write(90);
        delay(100);
        servo.write(135);
        delay(100);
        servo.write(180);
        delay(100);
        servo.write(135);
        delay(100);
      }
      else if(decTemp)
      {
        servo.write(90);
        delay(100);
        servo.write(45);
        delay(100);
        servo.write(0);
        delay(100);
        servo.write(45);
        delay(100);
      }

      delay(2000);
    }

For the incTemp and decTemp variables I will use an interrupt to detect when the Bluetooth paired device is sending a command to activate the servomotor. But for now, as it can be seen, the blocks that ask the servo to rotate cannot be reached. For the layout I will try to find a simulator that provides the components I use and I will come back with the design.

**Later edit**, after following ***Majenko***'s advice

Here is the currently working code. An answer with the full implementation will come when the project is complete.

    #include <Servo.h>

    int txPin = 1;
    int rxPin = 0;
    int digitalPin = 7; // KY-028 digital interface
    int analogPin = A2; // KY-028 analog interface
    int angle = 0;
    int temp;
    bool incTemp = false, decTemp = false;

    Servo servo;

    void setup() {
      pinMode(digitalPin, INPUT);
      pinMode(analogPin, INPUT);

      Serial.begin(9600);
    }

    void loop() {
      temp = analogRead(analogPin);
      Serial.print("T");
      Serial.print(temp);
      Serial.println();

      if(incTemp)
      {
        servo.attach(11);
        delay(100);

        servo.write(90);
        delay(100);
        servo.write(135);
        delay(100);
        servo.write(180);
        delay(100);
        servo.write(135);
        delay(100);

        servo.detach();
        delay(100);
      }
      else if(decTemp)
      {
        servo.attach(11);
        delay(100);

        servo.write(90);
        delay(100);
        servo.write(45);
        delay(100);
        servo.write(0);
        delay(100);
        servo.write(45);
        delay(100);

        servo.detach();
        delay(100);
      }

      delay(2000);
    }

title: Servomotor and Bluetooth module block each other

Answers: 1

body:
So, I got carried away with my exams and I forgot to come back with an update and a solution. To take it short, I added a new source of power to the circuit and I am only turning the servo on when needed to rotate, then turn it off again. The code can be seen below:

    #include <Servo.h>
    #include <SoftwareSerial.h>

    int rxPin = 2;
    int txPin = 3;
    int digitalPin = 7; // KY-028 digital interface
    int analogPin = A2; // KY-028 analog interface
    int servoPin = 11;

    int angle = 0;
    int temp;

    const int minTemp = 150;
    const int maxTemp = 350;
    const int minAngle = 0;
    const int maxAngle = 180;
    const char sendDataPackageStartByte = 'T';
    const int receiveDataPackageStartByteVal = 83; //"S"
    const int receiveDataPackageEndByteVal = 13;
    const int communicationDelay = 1000;
    const int servoDelay = 100;

    SoftwareSerial BT(rxPin,txPin);

    Servo servo;
    void setup() {
      pinMode(digitalPin, INPUT);
      pinMode(analogPin, INPUT);

      Serial.begin(9600);
      BT.begin(9600);
    }

    void loop() {
      if(BT.available() <= 0)
      {
        temp = analogRead(analogPin);
        BT.print(sendDataPackageStartByte);
        BT.print(temp/100);
        BT.print(temp/10);
        BT.print(temp);
        BT.println();
        delay(communicationDelay);
      }
      else
      {
        readData();
      }
    }

    void readData()
    {
      if (BT.available())
      {
        char temp[3];
        while(BT.available() > 0)
        {
          char crtByte = BT.read();
          if (crtByte == receiveDataPackageStartByteVal)
          {
            temp[0] = BT.read();
            temp[1] = BT.read();
            temp[2] = BT.read();

            if(BT.read() != receiveDataPackageEndByteVal)
            {
              return;
            }

            break;
          }
        }

        int desiredTemp = atoi(temp);
        int desiredAngle = map(desiredTemp, minTemp, maxTemp, minAngle, maxAngle);
        printDataToSerial(desiredTemp, desiredAngle);

        turnServo(desiredAngle); //attach servo, write value, dettach
      }
    }

    void printDataToSerial(int desiredTemp, int desiredAngle)
    {
      Serial.println("Desired Temperature:");
      Serial.println(desiredTemp);

      Serial.println("Desired Angle:");
      Serial.println(desiredAngle);
    }

    void turnServo(int angle)
    {
      servo.attach(servoPin);
      delay(servoDelay);
      servo.write(angle);
      delay(servoDelay);
      servo.detach();
      delay(servoDelay);
    }

Also, here would be the layout of my final circuit:

[![circuit][1]][1]

Basically what I wanted to achieve was sending and displaying the current temperature from an Arduino device to an Android one, then allow the user to adjust the temperature, simulating this with a servo commanded over Bluetooth. For those interested in the Android part as well (and the whole project actually), [here][2] is the link to the project repository on GitHub. The Android part is written with C# in the Xamarin Android framework. I hope this helps anyone landing here, good luck! :D

  [1]: https://i.stack.imgur.com/oZSZj.png
  [2]: https://github.com/GabrielStancu/AndroidTemperatureSensor


body:
I have recently been working on a project that I had initially been designing with an Arduino Nano, and I was able to create functioning code for my application, but for cost / space reduction I decided to port the application to an ATTiny13 (because I had a few on hand). The problem is that for some reason, I cannot get the interrupt on the device to behave properly, and I was wondering if anybody could possibly give me a hand. I already performed a few experiments to narrow the problem down, and I think I understand the nature of the problem, but I have no idea on how to mitigate it.

Here is a rough schematic of my setup:

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

And here is the code I started with:
```
// Pin defines
#define ALERT_LED 4

// Variables
bool LED_STATE = false;

ISR(PCINT0_vect) {
  LED_STATE = true;
}

void setup() {
  pinMode(ALERT_LED, OUTPUT);

  // Configure the button-pin to have a pull-up
  DDRB |= (1<<DDB3);
  PORTB |= (1<<PORTB3);

  // Enable a pin-change interrupt on the PCINT3 (falling-edge)
  MCUCR |= (1 << ISC01);  // This and following line setup for falling-edge
  MCUCR &= ~(1 << ISC00);
  GIMSK |= (1 << PCIE);   // Enable pin-change interrupts
  PCMSK |= (1 << PCINT3); // Setup the pin-mask so that PB3 triggers the interrupt
  sei();                  // enable all interrupts

}

void loop() {
  if(LED_STATE == true) {
    digitalWrite(ALERT_LED, HIGH);
    delay(2000);
    digitalWrite(ALERT_LED, LOW);
    delay(2000);
    LED_STATE = false;
  }
}
```

In theory, this should setup the pin that the button is on to have a pull-up resistor internally, and when the button is pressed, it should trigger a falling-edge interrupt which would thus set "LED_STATE" equal to 1. When the code returns to the main loop, it should see the flag and blink the LED before clearing the flag.

Now before I go any further, here is what I validated up to this point:

1.) The LED circuit is definitely wired up properly because I can manually set the "LED_STATE" flag to true in the main loop, and it will constantly blink at a rate of about once a second (given the clock frequency of 600kHz)

2.) The pull-up is definitely being configured properly, as I can see the voltage sitting at 5V until I press the button at which point the voltage falls to 0V.

So I decided to experiment a bit, and I set the LED high inside the interrupt, and removed that line from the main loop to see if the interrupt was even working, and to my surprise the LED was actually turning on, but it was not turning off:

```
// Pin defines
#define ALERT_LED 4

// Variables
bool LED_STATE = false;

ISR(PCINT0_vect) {
  LED_STATE = true;
  digitalWrite(ALERT_LED, HIGH);
}

void setup() {
  pinMode(ALERT_LED, OUTPUT);

  // Configure the button-pin to have a pull-up
  DDRB |= (1<<DDB3);
  PORTB |= (1<<PORTB3);

  // Enable a pin-change interrupt on the PCINT3 (falling-edge)
  MCUCR |= (1 << ISC01);  // This and following line setup for falling-edge
  MCUCR &= ~(1 << ISC00);
  GIMSK |= (1 << PCIE);   // Enable pin-change interrupts
  PCMSK |= (1 << PCINT3); // Setup the pin-mask so that PB3 triggers the interrupt
  sei();                  // enable all interrupts

}

void loop() {
  if(LED_STATE == true) {
    //digitalWrite(ALERT_LED, HIGH);
    delay(2000);
    digitalWrite(ALERT_LED, LOW);
    delay(2000);
    LED_STATE = false;
  }
}
```

At this point, I started to think that the ISR was not returning to the main loop or something, but by adding an 'else' case to shut the LED off in the main loop, I could see that the loop was definitely running after the ISR, because the LED would not turn on (implying that the main loop had to be shutting it off the moment the ISR returned to the loop).

```
// Pin defines
#define ALERT_LED 4

// Variables
bool LED_STATE = false;

ISR(PCINT0_vect) {
  LED_STATE = true;
  digitalWrite(ALERT_LED, HIGH);
}

void setup() {
  pinMode(ALERT_LED, OUTPUT);

  // Configure the button-pin to have a pull-up
  DDRB |= (1<<DDB3);
  PORTB |= (1<<PORTB3);

  // Enable a pin-change interrupt on the PCINT3 (falling-edge)
  MCUCR |= (1 << ISC01);  // This and following line setup for falling-edge
  MCUCR &= ~(1 << ISC00);
  GIMSK |= (1 << PCIE);   // Enable pin-change interrupts
  PCMSK |= (1 << PCINT3); // Setup the pin-mask so that PB3 triggers the interrupt
  sei();                  // enable all interrupts

}

void loop() {
  if(LED_STATE == true) {
    //digitalWrite(ALERT_LED, HIGH);
    delay(2000);
    digitalWrite(ALERT_LED, LOW);
    delay(2000);
    LED_STATE = false;
  }
  else {
 digitalWrite(ALER_LED, LOW);
  }
}
```

At this point, I can really only think that there must be a problem with how I am defining the "LED_STATE" parameter, because all signs point towards this variable not actually holding the information properly when traversing from the ISR back to the loop. I don't see what would be the problem though since I defined the parameter globally. Can anybody lend a hand here, this is honestly the last thing I need to finish this part of the project, and I am honestly at a bit of a loss at this point.

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

title: ATTiny13 Interrupt Issue

Answers: 1

body:
You would want your `bool LED_STATE = false;` to be [volatile qualified][1] like `volatile bool LED_STATE = false;` otherwise the compiler's optimizer may assume that the value cannot be changing between loads and this can cause bugs in the generated code.  This sounds like the principal problem you're having.

The `ISC01` and `ISC00` in `MCUCR` are for controlling edges detected on the "external interrupt" INT0 pin, which is PB1, package pin 6.  This is essentially what `attachInterrupt()` does, which should be available to you in your board support package.  If you can, it's probably best to just use that.  In the case of using `attachInterrupt()` the use of `volatile` would still apply.

The other pins, like the one you've chosen, only only do **P**in **C**hange interrupts, hence PCINTn rather than INTn.  Pin change interrupts only fire to tell that a pin changed, but not which pin (out of the group) or in what direction it changed.  That is, it's ignoring what you've set in `MCUCR`.

If you want an external interrupt's ability to detect falling or rising edges using PCINTn interrupts, you must effectively synthesize this in software by tracking the old and new states of the pins, XORing them to determine what changed, and then either looking at the old or new state to determine what direction.  NicoHood's [PinChangeInterrupt library][2] does this [for you][3], and appears to [support the ATTiny13][4].  Likewise, `volatile` usage applies here as well.

  [1]: https://www.arduino.cc/en/pmwiki.php?n=Reference/Volatile
  [2]: https://github.com/NicoHood/PinChangeInterrupt
  [3]: https://github.com/NicoHood/PinChangeInterrupt/blob/1.2.8/src/PinChangeInterrupt0.cpp#L42
  [4]: https://github.com/NicoHood/PinChangeInterrupt#supported-pins-for-pinchangeinterrupt


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

```c++
#include <Adafruit_Fingerprint.h>
#include  <SoftwareSerial.h>
#include <LiquidCrystal.h>

uint8_t id;
int getFingerprintIDez();
//pin #16 is IN from sensor (GREEN wire)
//pin #15 is OUT from arduino (WHITE wire)
int Contrast = 100;
SoftwareSerial mySerial(52, 16);
LiquidCrystal lcd(13, 12, 11, 10, 9, 8); // initialize the library with the numbers of the interface pins
Adafruit_Fingerprint finger = Adafruit_Fingerprint(&mySerial);
#define S1 22 //Button candidate A
#define S2 24 // Button candidate B
#define S3 26 // Button candidate c
#define S4 28 // Button candidate D
#define S5 30 // Button Result
#define S6 2 // Button submit
#define S7 32 // Button to cast vote
int can1 = 0;
int can2 = 0;
int can3 = 0;
int can4 = 0;
int total;
SoftwareSerial ESP8266(50, 18);// RX, TX

void setup() {
  Serial.begin(9600); // initialize the serial communications:
  lcd.begin(16, 2); lcd.clear();
  lcd.print("  Polling Day  ");
  lcd.setCursor(0, 1);
  lcd.print("      UPM      ");
  delay(2000);

  mainpage();

  pinMode(13, OUTPUT);
  pinMode(12, OUTPUT);
  pinMode(11, OUTPUT);
  pinMode(A0, INPUT);

  finger.begin(57600); // set the data rate for the sensor serial port

  pinMode(S1, INPUT);
  pinMode(S2, INPUT);
  pinMode(S3, INPUT);
  pinMode(S4, INPUT);
  pinMode(S5, INPUT);
  pinMode(S6, INPUT);
  pinMode(S7, INPUT);

  ESP8266.begin(9600);

  digitalWrite(S1, HIGH);
  digitalWrite(S2, HIGH);
  digitalWrite(S3, HIGH);
  digitalWrite(S4, HIGH);
  digitalWrite(S5, HIGH);
  digitalWrite(S6, HIGH);
  digitalWrite(S7, HIGH);

  SendCommand("AT+RST", "Ready");
  delay(5000);
  SendCommand("AT+CWMODE=1", "OK");
  SendCommand("AT+CIFSR", "OK");
  SendCommand("AT+CIPMUX=1", "OK");
  SendCommand("AT+CIPSERVER=1,80", "OK");
}

void loop() { // run over and over again
  getFingerprintID();
  delay(100);
  digitalWrite (13, HIGH);
  if (digitalRead(S5) == 0) { // To view the result for admin only
    int total = can1 + can2 + can3 + can4;
    lcd.clear();
    lcd.setCursor(1, 0);
    lcd.print("1");
    lcd.setCursor(1, 1);
    lcd.print(can1);
    lcd.setCursor(5, 0);
    lcd.print("2");
    lcd.setCursor(5, 1);
    lcd.print(can2);
    lcd.setCursor(9, 0);
    lcd.print("3");
    lcd.setCursor(9, 1);
    lcd.print(can3);
    lcd.setCursor(13, 0);
    lcd.print("4");
    lcd.setCursor(13, 1);
    lcd.print(can4);
    delay(4000);
    if (total) {
      if ((can1 > can2 && can1 > can3 && can1 > can4)) {
        lcd.clear();
        lcd.print("Can A is Winner");
        delay(3000);
        lcd.clear();
      } else if ((can2 > can1 && can2 > can3 && can2 > can4)) {
        lcd.clear();
        lcd.print("Can B is Winner");
        delay(3000);
        lcd.clear();
      } else if ((can3 > can1 && can3 > can2 && can3 > can4)) {
        lcd.clear();
        lcd.print("Can C is Winner");
        delay(3000);
        lcd.clear();
      } else if (can4 > can1 && can4 > can2 && can4 > can3) {
        lcd.setCursor(0, 0);
        lcd.clear();
        lcd.print("Can D is Winner");
        delay(3000);
        lcd.clear();
      } else if (can4 > can1 && can4 > can2 && can4 > can3) {
        lcd.setCursor(0, 0);
        lcd.clear();
        lcd.print("Can D is Winner");
        delay(3000);
        lcd.clear();
      } else {
        lcd.clear();
        lcd.print(" Tie Up Or ");
        lcd.setCursor(0, 1);
        lcd.print(" No Result ");
        delay(3000);
        lcd.clear();
      }
    } else {
      lcd.clear();
      lcd.print("No Voting....");
      delay(3000);
      lcd.clear();
    }
    can1 = 0; can2 = 0; can3 = 0; can4 = 0, total = 0;
    lcd.clear();
    adminpage();
  }

  if (digitalRead(S7) == 0) { //To cast avote for user
    voterpage();
  }

  if (digitalRead(S1) == 0) {
    can1++;
    votereceived();
    mainpage();
  }

  while (digitalRead(S1) == 0);
  if (digitalRead(S2) == 0) {
    can2++;
    votereceived();
    mainpage();
  }
  while (digitalRead(S2) == 0);
  if (digitalRead(S3) == 0) {
    can3++;
    votereceived();
    mainpage();
  }
  while (digitalRead(S3) == 0);
  if (digitalRead(S4) == 0) {
    can4++;
    votereceived();
    mainpage();
  }
  while (digitalRead(S4) == 0);
  if (digitalRead(S6) == 0) {
    lcd.clear();
    lcd.print("Submitting...");
    delay(1000);
    ESP8266.println("AT+CIPSEND=0,23");
    delay(1000);
    SendCommand("AT+CIPCLOSE=0", "OK");
  }
  String IncomingString = "";
  boolean StringReady = false;

  while (ESP8266.available()) {
    IncomingString = ESP8266.readString();
    StringReady = true;
  }

  if (StringReady) {
    Serial.println("Received String: " + IncomingString);

    if (IncomingString.indexOf("LED=ON") != -1) {
      digitalWrite(LED, HIGH);
    }

    if (IncomingString.indexOf("LED=OFF") != -1) {
      digitalWrite(LED, LOW);
    }
  }

  boolean SendCommand(String cmd, String ack) {
    ESP8266.println(cmd); // Send "AT+" command to module
    if (!echoFind(ack)) // timed out waiting for ack string
      return true; // ack blank or ack found
  }

  boolean echoFind(String keyword) {
    byte current_char = 0;
    byte keyword_length = keyword.length();
    long deadline = millis() + TIMEOUT;
    while (millis() < deadline) {
      if (ESP8266.available()) {
        char ch = ESP8266.read();
        Serial.write(ch);
        if (ch == keyword[current_char])
          if (++current_char == keyword_length) {
            Serial.println();
            return true;
          }
      }
    }
    return false; // Timed out
  }
}

uint8_t getFingerprintID() {
  uint8_t p = finger.getImage();
  switch (p) {
    case FINGERPRINT_OK:
      lcd.clear();
      lcd.print(" Image taken... ");
      delay(1000);
      break;
    case FINGERPRINT_NOFINGER:
      return p;
    case FINGERPRINT_PACKETRECIEVEERR:
      return p;
    case FINGERPRINT_IMAGEFAIL:
      return p;
    default:
      return p;
  }

  // OK success!
  p = finger.image2Tz();
  switch (p) {
    case FINGERPRINT_OK:
      break;
    case FINGERPRINT_IMAGEMESS:
      return p;
    case FINGERPRINT_PACKETRECIEVEERR:
      return p;
    case FINGERPRINT_FEATUREFAIL:
      return p;
    case FINGERPRINT_INVALIDIMAGE:
      return p;
    default:
      return p;
  }

  // OK converted!
  p = finger.fingerFastSearch();
  if (p == FINGERPRINT_OK) {
    if (finger.fingerID == 26) {
      lcd.clear();
      lcd.setCursor(1, 0);
      lcd.print("Redirecting to");
      lcd.setCursor(1, 1);
      lcd.print("Admin process");
    } else {
      lcd.clear();
      lcd.setCursor(2, 0);
      lcd.print("Valid Voter!");
      lcd.setCursor(2, 1);
      lcd.print("ID : ");
      lcd.print(finger.fingerID);
    }

    digitalWrite(11, HIGH);
    delay(1000);
    digitalWrite(11, LOW); // turn on green LED to indicate match
  } else if (p == FINGERPRINT_NOTFOUND) {
    lcd.clear();
    lcd.setCursor(1, 0);
    lcd.print("Unregistered");
    lcd.setCursor(3, 1);
    lcd.print("Voter!");
    delay(1000);
    lcd.clear();
    lcd.setCursor(2, 0);
    lcd.print("scan finger");
    lcd.setCursor(6, 1);
    lcd.print("again");
    return p;
  } else {
    return p;
  }

  // IF FOUND A MATCH............
  lcd.clear();
  lcd.setCursor(0, 0);
  lcd.print("Found ID #");

  if (finger.fingerID == 26) {
    adminpage();
  } else {
    voterpage();
  }
}

// returns -1 if failed, otherwise returns ID #
int getFingerprintIDez() {
  uint8_t p = finger.getImage();
  if (p != FINGERPRINT_OK) return -1;
  p = finger.image2Tz();
  if (p != FINGERPRINT_OK) return -1;
  p = finger.fingerFastSearch();
  if (p != FINGERPRINT_OK) return -1;
  // found a match!
  digitalWrite(13, LOW);
  delay(10);
  digitalWrite(13, HIGH);
  delay(10);
  lcd.clear();
  lcd.setCursor(0, 0);
  lcd.print("Found ID # ");
  lcd.print(finger.fingerID);
  lcd.setCursor(0, 1);
  lcd.print("confidence ");
  lcd.print(finger.confidence);
  return finger.fingerID;
}

void voterpage() {
  lcd.clear();
  lcd.setCursor(1, 0);
  lcd.print("Candidate 1");
  lcd.setCursor(1, 1);
  lcd.print("Mohd Faiz");
  delay(3000);
  lcd.clear();
  lcd.setCursor(1, 0);
  lcd.print("Candidate 2");
  lcd.setCursor(1, 1);
  lcd.print("Siti Nur Ila");
  delay(3000);
  lcd.clear();
  lcd.setCursor(1, 0);
  lcd.print("Candidate 3");
  lcd.setCursor(1, 1);
  lcd.print("Muhammad Aus");
  delay(3000);
  lcd.clear();
  lcd.setCursor(1, 0);
  lcd.print("Candidate 4");
  lcd.setCursor(1, 1);
  lcd.print("Wan zakaria");
  delay(3000);
  lcd.clear();
  lcd.setCursor(1, 0);
  lcd.print("Choose 1 only");
  lcd.setCursor(1, 1);
  lcd.print("1");
  lcd.setCursor(5, 1);
  lcd.print("2");
  lcd.setCursor(9, 1);
  lcd.print("3");
  lcd.setCursor(13, 1);
  lcd.print("4");
}

void votereceived() {
  lcd.clear();
  lcd.setCursor(0, 0);
  lcd.print("Vote Received");
  lcd.setCursor(2, 1);
  lcd.print("Thank You :)");
  delay(2000);
}

void adminpage() {
  lcd.clear();
  lcd.setCursor(3, 0);
  lcd.print("1");
  lcd.setCursor(1, 1);
  lcd.print("Result");
  lcd.setCursor(11, 0);
  lcd.print("2");
  lcd.setCursor(8, 1);
  lcd.print(" Submit");
  delay(2000);
}

void mainpage() {
  lcd.clear(); lcd.setCursor(0, 0); lcd.print("Scan your finger");
}
```

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

title: Why am I getting a "SendCommand was not declared" error?

Answers: 1

body:
Both `boolean SendCommand()` and `boolean echoFind()` are defined inside `loop()`, and they shouldn't be; it is not allowed to define functions inside functions.

Take them out of `loop()` and define them at (move them to) the same level as `uint8_t getFingerprintID()`, etc.


body:
I am trying to burn bootloader on Arduino UNO using MEGA2560 as the programmer,
I followed the steps stated [here](https://www.arduino.cc/en/Tutorial/BuiltInExamples/ArduinoISP) but still get the error below:

```
avrdude: Version 6.3-20190619
         Copyright (c) 2000-2005 Brian Dean, http://www.bdmicro.com/
         Copyright (c) 2007-2014 Joerg Wunsch

         System wide configuration file is "/home/arduino/arduino-nightly/hardware/tools/avr/etc/avrdude.conf"
         User configuration file is "/home/webdev/.avrduderc"
         User configuration file does not exist or is not a regular file, skipping

         Using Port                    : /dev/ttyUSB0
         Using Programmer              : stk500v1
         Overriding Baud Rate          : 19200
         AVR Part                      : ATmega328P
         Chip Erase delay              : 9000 us
         PAGEL                         : PD7
         BS2                           : PC2
         RESET disposition             : dedicated
         RETRY pulse                   : SCK
         serial program mode           : yes
         parallel program mode         : yes
         Timeout                       : 200
         StabDelay                     : 100
         CmdexeDelay                   : 25
         SyncLoops                     : 32
         ByteDelay                     : 0
         PollIndex                     : 3
         PollValue                     : 0x53
         Memory Detail                 :

                                  Block Poll               Page                       Polled
           Memory Type Mode Delay Size  Indx Paged  Size   Size #Pages MinW  MaxW   ReadBack
           ----------- ---- ----- ----- ---- ------ ------ ---- ------ ----- ----- ---------
           eeprom        65    20     4    0 no       1024    4      0  3600  3600 0xff 0xff
           flash         65     6   128    0 yes     32768  128    256  4500  4500 0xff 0xff
           lfuse          0     0     0    0 no          1    0      0  4500  4500 0x00 0x00
           hfuse          0     0     0    0 no          1    0      0  4500  4500 0x00 0x00
           efuse          0     0     0    0 no          1    0      0  4500  4500 0x00 0x00
           lock           0     0     0    0 no          1    0      0  4500  4500 0x00 0x00
           calibration    0     0     0    0 no          1    0      0     0     0 0x00 0x00
           signature      0     0     0    0 no          3    0      0     0     0 0x00 0x00

         Programmer Type : STK500
         Description     : Atmel STK500 Version 1.x firmware
         Hardware Version: 2
         Firmware Version: 1.18
         Topcard         : Unknown
         Vtarget         : 0.0 V
         Varef           : 0.0 V
         Oscillator      : Off
         SCK period      : 0.1 us

avrdude: AVR device initialized and ready to accept instructions

Reading | ################################################## | 100% 0.02s

avrdude: Device signature = 0x000000 (retrying)

Reading | ################################################## | 100% 0.02s

avrdude: Device signature = 0x000000 (retrying)

Error while burning bootloader.
Reading | ################################################## | 100% 0.02s

avrdude: Device signature = 0x000000
avrdude: Yikes!  Invalid device signature.
         Double check connections and try again, or use -F to override
         this check.

avrdude done.  Thank you.
```
**Note:** The Arduino UNO stopped responding when I mistakenly short-circuited a connection, I mistakenly passed 12v to one of the header pins of sensor shield mounted on the board.

**How it was connected**
[![Connection diagram][1]][1]

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

title: Error while burning bootloader

Answers: 1

body:
Based on this:

> Note: The Arduino UNO stopped responding when I mistakenly
> short-circuited a connection, I mistakenly passed 12v to one of the
> header pins of sensor shield mounted on the board.

There are no I/O pins on the Arduino that are 12V tolerant.  You have almost certainly "fried" your Uno board.  It's possible the only casualty is the ATMega chip itself and replacements are available from a number of sources or you can purchase a "raw" one from an electronics reseller and use your programmer setup above to burn your own boot loader.

It's also quite likely that your sensor board is damaged as well.

From the Microchip datasheet:

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

You want something like this:

[Adafruit Pre-programmed ATMega168p][2]

Buy several, accidents happen!

  [1]: https://i.stack.imgur.com/qVbVn.png
  [2]: https://www.adafruit.com/product/123


body:
I'm using the PCM(http://highlowtech.org/?p=1963) library on the Arduino nano, I'm plugging the speaker(https://www.amazon.com/gp/product/B07WZP4QFK/ref=ox_sc_act_title_3?smid=A2O4FZXIRZDLHA&psc=1) into pin 11 and ground, but the example file won't work.

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

[![enter image description here][2]][2]

[![enter image description here][3]][3][![enter image description here][4]][4]

  [1]: https://i.stack.imgur.com/wXNYn.png
  [2]: https://i.stack.imgur.com/lV2os.png
  [3]: https://i.stack.imgur.com/dgugk.png
  [4]: https://i.stack.imgur.com/p40r5.png

title: The PCM libary won't work on an Arduino Nano

Answers: 1

body:
I guess the Nano had a sketch which was setting pin 11 HIGH (using SPI?) as you turned it on with a 4 Ohm speaker attached without any other resistance. It created a short circuit and damaged the pin's circuit.

Using tone() or the PCM library with a speaker connected without additional resistor doesn't damage the pin immediately because it is then HIGH only for very short moments, but it stresses the pin circuit too.

The linked page recommends to use direct speaker connection because it is much louder then with a resistor in series, but this is a wrong advice. It should recommend an amplifier module for example with LM386 IC.

A piezo speaker has higher resistance so it can be connected directly to Arduino pin, but a piezo sounds loud only in high frequencies so with the PCM library the sound is like whispering.


body:
I have a 8x8 led matrix. I'm using LedControl.h library to control the matrix, which has 3 ways to light up the leds: setLed, setRow and setColumn. I've found that setColumn it's really slow, it's using setLed to print columns. With all my code, I can only print 3 times a second with setColumn. The function setRow is way faster, I'm guessing that the design of the matrix is allowing to print the rows directly. I can print more than 10 times a second with setRow, so I have to use it, since speed is crucial to my project. In my code, the data i have to print is stored in an array of 8 bytes. This is how it looks like when I use setColumn

    for(int i = 7; i >= 0; i--)
        lc.setColumn(0, i, vector[i]);
i is the row to be printed, and vector[i] is a byte value, indicating which leds to be on or off. Column 0 is the left-most one, while column 7 is the right-most one, so i go from 7 to 0 to print from right to left, because that's what I have to do. My goal is to transform somehow to data in vector[i], to data that I can use it using setRow. So that's what I've done so far.

    byte mask = 128, x;
    for (int j = 0; j < 8; j++){
      x = 0;
      for(int p = 0; p < 8; p++){
        x = x | (valueVector[p] & mask);
        if (p != 7)
          x = x >> 1;
      }
      if (j != 7)
      mask = mask >> 1;
      lc.setRow(0, j, x);
    }

Now i print the rows from row 0 to row 7, from top to bottom. Since I'm printing from top to bottom, this means I have to take the last bit of every column (last bit of every element in vector), and put it in a byte variable. I was thinking to make a byte mask = 128 (b1000000, do a AND logic between to mask and the vector value in order to take the bit I'm looking for, and then making a OR to put the bit in the x byte. After every mask operation, I shift the x variable to the right, in order to make space for the next bit. After i'm done with a row, I shift the mask to the right, in order to take the second bit from the value in the vector. The result I get, is quite odd, I can't explain it, it's not good at all. What I'm i doing wrong with the mask and shifts? I hope I explained well what I'm trying to do. If necessary, I can provide more information. Thanks.

title: How do I transform data for a column to data for a row, for a led matrix

Answers: 1

body:
You use a mask `10000000`. With each iteration of the outer loop the `1` in the mask is shifted to the right. `01000000` -> `00100000` -> `00010000`. Let's say we are in the 2nd iteration the mask is `01000000`. `x = x | (valueVector[p] & mask);` takes the 2nd bit (counted from left) and sets it at the 2nd position in the x value. But this position contains the bit from the last iteration (as you shifted it to this position).

Possible solution: (I have no compiler at hand. So hopefully it is correct. ;-)

    byte x;

    for ( int j=0; j<8; j++ )
    {
       x = 0;

       for ( int p=0; p<8; p++ )
         x = x | ((valueVector[p] & (1 << p)) >> p);

       lc.setRow(0, j, x);
    }


body:
I am making a fun LED Christmas tree project using this code:

<!-- language:c++ -->

    // Source location \\adam\U_DRIVE\_BACKED_UP\_Documents\Electronics\XmasTree
    #include <FastLED.h>
    #define NUM_LEDS 102
    #define DATA_PIN 6
    CRGB leds[NUM_LEDS];
    void setup() {
      Serial.begin(9600);
      Serial.println("Boot");
      // put your setup code here, to run once:
      FastLED.addLeds<NEOPIXEL, DATA_PIN>(leds, NUM_LEDS);

      //  SetRandomLight;
      SetAllOff();
      delay(10); //Delay before getting going.
      BootUp();
      randomSeed(analogRead(0) + analogRead(1) + analogRead(2) + analogRead(3) + analogRead(4) + analogRead(5) + analogRead(6));
    }

    void loop() {
      // put your main code here, to run repeatedly:
      SingleDrift();
      FastLED.show();
      //delay(random(50));
    }

    void FadeAll(int x)
    {
      for (int i = 0; i < NUM_LEDS; i++)
      {
        leds[i].subtractFromRGB(x);
      }
    }

    void SetRandomLight() {
      for (int i = 0; i < NUM_LEDS; i++)
      {
        leds[i].r = random(128);
        leds[i].g = random(128);
        leds[i].b = random(128);
        Serial.println(i);
      }
    }

    void SetAllOff()
    {
      Serial.println("Blanking all.");
      for (int i = 0; i < NUM_LEDS; i++)
      {
        leds[i] = 0x000000;
        leds[i].r = 0;
        leds[i].g = 0;
        leds[i].b = 0;

        //Serial.println(i);
      }
      FastLED.show();
    }

    void SingleDrift() {
      int mini = 5;
      int maxi = 255;
      FastLED.setBrightness(maxi);
      for (int i = 0; i < NUM_LEDS; i++)
      {
        if (leds[i].r > 64) leds[i].r = leds[i].r - 8;
        if (leds[i].g > 64) leds[i].g = leds[i].g - 8;
        if (leds[i].b > 64) leds[i].b = leds[i].b - 8;

        int rnd = random(10);
        if (rnd == 1 && leds[i].r >= 2) leds[i].r = leds[i].r - 1;
        if (rnd == 2 && leds[i].g >= 2) leds[i].g = leds[i].g - 1;
        if (rnd == 3 && leds[i].b >= 2) leds[i].b = leds[i].b - 1;
        if (rnd == 4) leds[i].fadeToBlackBy(2);
        if (rnd == 5) leds[i].g++;
        //if (rnd == 6 && leds[i].g < 240) leds[i].g = leds[i].g + 1;
        //if (rnd == 7 && leds[i].b < 240) leds[i].b = leds[i].b + 1;
        if (leds[i].g < 2) leds[i].g = 2;
      }

      int i = random(NUM_LEDS);
      Serial.println(i);
      if (leds[i].r + leds[i].g + leds[i].b > 10) return; //If the LED is still bright, do not change it.
      if (random(100) > 80)
      {
        //Choose a colour
        int r = random(20);
        switch (r)
        {
          case 99:
            for (i = 0; i < NUM_LEDS; i++)
            {
              int x = leds[i].r;
              leds[i].r = leds[i].b;
              leds[i].b = x;
            }

          case 1:
          case 2:
          case 3:
            leds[i] = CRGB::Red;
            break;
          case 4:
          case 5:
          case 6:
            leds[i] = CRGB::Green;
            break;
          case 7:
            leds[i] = CRGB::Blue;
            break;
          case 8:
            leds[i].r = random(128, 255);
            leds[i].g = random(128, 255);
            leds[i].b = random(128, 255);
          case 9:
            leds[i] = CRGB::Yellow;
            break;
          case 10:
            leds[i] = CRGB::Crimson;
            break;
          case 12:
            leds[i] = CRGB::Aqua;
            break;
          case 13:
            leds[i] = CRGB::BlueViolet;
            break;
          case 14:
            leds[i] = CRGB::MidnightBlue;
            break;
          case 15:
            leds[i].setRGB( 255, 255, 255);
            break;
        }
      }
    }

    void BootUp()
    {
      for (int i = 0; i < NUM_LEDS; i++)
      {
        leds[i].b = map(i, 0, NUM_LEDS, 0, 255);
        leds[i].r = map(i, NUM_LEDS, 0, 0, 255);
      }
      for (int pc = 0; pc < 100; pc++)
      {
        FastLED.setBrightness(pc);
        FastLED.show();
        delay(3);
      }
      for (int i = 0; i < NUM_LEDS; i++)
      {
        leds[i] = -leds[i];
        FastLED.show();
        delay(10);
      }

      for (int i = 0; i < NUM_LEDS; i++)
      {
        leds[i].setRGB( 0, 10, 0);

        FastLED.show();
        delay(10);
      }
    }

The LED cycle currently fades to green every time, so I would like to add different color fades. However, I could not figure out how to change the color/timing after poking around. Could someone please point me in the right direction for what I changes to the code I need to make?

title: Arduino fade to color change

Answers: 2

body:
I think line 84 that keeps the leds green instead of going black. I think line 81 is there to create some kind of shimmer effect on some of the green leds and to skew the color to a bit more green. So I removed those. To prevent the leds from going to black instead of green, I added an if statement that stops any further fading out, if the total "brightness" is `16` or lower. I have no idea how this will look. You might have to tweak this 16-value a bit.

That's the best I could do without a full rewrite of the code.

```
void SingleDrift() {
  int mini = 5;
  int maxi = 255;
  FastLED.setBrightness(maxi);
  for (int i = 0; i < NUM_LEDS; i++)
  {
    if (leds[i].r > 64) leds[i].r = leds[i].r - 8;
    if (leds[i].g > 64) leds[i].g = leds[i].g - 8;
    if (leds[i].b > 64) leds[i].b = leds[i].b - 8;

    if ( (leds[i].r + leds[i].g + leds[i].b) > 16) // prevent fading to black
    {
      int rnd = random(10);
      if (rnd == 1 && leds[i].r >= 2) leds[i].r = leds[i].r - 1;
      if (rnd == 2 && leds[i].g >= 2) leds[i].g = leds[i].g - 1;
      if (rnd == 3 && leds[i].b >= 2) leds[i].b = leds[i].b - 1;
      if (rnd == 4) leds[i].fadeToBlackBy(2);
      //if (rnd == 5) leds[i].g++;
      //if (rnd == 6 && leds[i].g < 240) leds[i].g = leds[i].g + 1;
      //if (rnd == 7 && leds[i].b < 240) leds[i].b = leds[i].b + 1;
      //if (leds[i].g < 2) leds[i].g = 2; // I think this line kept the leds green
    }
  }
  ...
```

body:
That code is a bit of a mess. It has some code that will never execute, as well as very confusing structure.

If it were me I would throw away that code and start over with code that does some other animation. You won't break anything, so play.

As to the code you posted:

It looks to me like the first for loop that cycles through all the LEDs is set to first fade all the LEDs down towards 0 brightness by 8 while their value is > 64.

After the global fade, it then uses a random number 0-9 to decide what to do next for each LED.

 1. If the random value is 1, 2, or 3, it reduces the red, green, or blue channels by 1.
 1. If the random value is 4, it drives the current LED to black.
 1. If the random value is 5, it increases the green channel of the current LED by 1.
finally, it sets the green channel of the current LED back to 2 if it drops below 2. **That means that every LED will end up with flicker with a dim green color unless the next section changes that LED's color to something different**.

I added "**this" comments to the lines that drive the LEDs towards green.

```
  for (int i = 0; i < NUM_LEDS; i++)
  {
    if (leds[i].r > 64) leds[i].r = leds[i].r - 8;
    if (leds[i].g > 64) leds[i].g = leds[i].g - 8;
    if (leds[i].b > 64) leds[i].b = leds[i].b - 8;

    int rnd = random(10);
    if (rnd == 1 && leds[i].r >= 2) leds[i].r = leds[i].r - 1;
    if (rnd == 2 && leds[i].g >= 2) leds[i].g = leds[i].g - 1;
    if (rnd == 3 && leds[i].b >= 2) leds[i].b = leds[i].b - 1;
    if (rnd == 4) leds[i].fadeToBlackBy(2);
    if (rnd == 5) leds[i].g++;  //**This will tend to make this LED flicker green.
    //if (rnd == 6 && leds[i].g < 240) leds[i].g = leds[i].g + 1;
    //if (rnd == 7 && leds[i].b < 240) leds[i].b = leds[i].b + 1;
    if (leds[i].g < 2) leds[i].g = 2; //**This will make each LED stop at dim green.
  }
```

If you want the LEDs to end up at some color other than green, you might want to change those last lines of the first for loop You could change that first section to something like this:

```
  for (int i = 0; i < NUM_LEDS; i++)
  {
    if (leds[i].r > 64) leds[i].r = leds[i].r - 8;
    if (leds[i].g > 64) leds[i].g = leds[i].g - 8;
    if (leds[i].b > 64) leds[i].b = leds[i].b - 8;

    int rnd = random(11);
    if (rnd == 1 && leds[i].r >= 2) leds[i].r = leds[i].r - 1;
    if (rnd == 2 && leds[i].g >= 2) leds[i].g = leds[i].g - 1;
    if (rnd == 3 && leds[i].b >= 2) leds[i].b = leds[i].b - 1;
    if (rnd == 4) leds[i].fadeToBlackBy(2);

    if (rnd == 5) leds[i].g++;  //**This will tend to make this LED flicker green.
    if (rnd == 6) leds[i].r++;  //**This will tend to make this LED flicker red.
    if (rnd == 7) leds[i].b++;  //**This will tend to make this LED flicker blue.

    if (rnd == 8) && (leds[i].g < 2) leds[i].g = 2; //**This will make the LED go dim green
    if (rnd == 9) && (leds[i].r < 2) leds[i].r = 2; //**This will make the LED go dim red
    if (rnd == 10) && (leds[i].b < 2) leds[i].b = 2; //**This will make the LED go dim blue
  }
```

Then it picks one random LED, and 20% of the time, does more random stuff to the color of that LED if it is dim enough. It uses a random value from 0-19 to decide what to do in the next switch statement. The first case is `case 99:`, which can never execute because the random value will never be greater than 19. For other values, it forces that LED to be a bright primary color, or maybe white, or maybe a color with random RGB values ranging from 128 to 255.


body:
I have ZEDF9P AND ARDUINO and connected them Via UART.
I have written program which is showing that NMEA strings are coming in arduino and arduino is filtering out if GPS jamming is taking place. Now once GPS signals are coming LCD show GPS:ok. oNCE GPS is jammed it is giving output as GPS:INVALID
.During this time it converts to GLONASS. I want to write GLONASS ENABLED on LCD once I get signals. But my problem is that I am unable to write code for the time once GLONASS is enabled. I want that once I switch on another system The system name should come on LCD automatically but I don't know where the code is wrong. Kindly help me with the code. (I am doing it with NEO6M as well so kindly ignore baudrate)

    #include <SoftwareSerial.h>
    #include <LiquidCrystal.h>
    LiquidCrystal lcd(12, 11, 5, 4, 3, 2);

    // Choose two Arduino pins to use for software serial
     int RXPin = 6;
     int TXPin = 7;

    //Default baud of NEO-6M is 9600
    int GPSBaud = 9600;

    // Create a software serial port called "gpsSerial"
    SoftwareSerial gpsSerial(RXPin, TXPin);

    #define GPSENABLE 2
    byte GPSBuffer[82];
    byte GPSIndex=0;
    #define MAX_NMEA 200 // Max characters in NMEA Sentence to accumulate

    float gpsSpeed;
    void processGGA(char *nmea)
    {
    // TODO
    }
    void processGLL(char *nmea)
    {
    // TODO
    }
    void processRMC(char *nmea)
    {
    char *token = strtok(nmea, ",");  // Split NMEA string with ',' delimiter
    if (token) // Is Token NULL?
    {
    int i;
    for(i=0; i<7; i++) // Process Fields, truncated
    {
     token = strtok(NULL, (i < 11) ? "," : "*"); // delimit based on expected termination
      if (!token) break; // NULL Token
      if (i == 1) // Field 1 Fix
      {
      lcd.clear();
        lcd.setCursor(0,0);
        if (token[0] == 'A')
         { lcd.print("GPS:OK");
        digitalWrite(9, HIGH);
        digitalWrite(8, LOW);}
        else if (token[0] == 'V')
          {delay(100);
            lcd.print("GPS:INVALID");
        for (int i = 0; i <= 100; i++) {
      digitalWrite(8, HIGH);
      delay(100);
      digitalWrite(8, LOW);
      delay(100);
      };
      uint8_t ubx_cfg_gnss[] = {
    0xB5,0x62,0x06,0x3E,0x2C,0x00, // UBX-CFG-GNSS
    0x00,0x00,0x10,0x05, // 16-Channels, 5-Constellations in list
    0x00,0x08,0x10,0x00,0x01,0x00,0x01,0x01, // GPS
    0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x01, // SBAS
    0x03,0x08,0x10,0x00,0x00,0x00,0x01,0x01, // GALILEO
    0x05,0x00,0x03,0x00,0x00,0x00,0x01,0x01, // BEIDOU
    0x06,0x08,0x0E,0x00,0x00,0x00,0x01,0x01, // GLONASS
    0xE8,0xFE }; // compute checksum
     Serial.write(ubx_cfg_gnss,sizeof(ubx_cfg_gnss));

          }
        else
          lcd.print("GPS:UNKNOWN");
      }
      if (i == 6) // Field 6 Speed Knots (Basically a Nautical Mile, or One Arc Minute)
       { gpsSpeed = atof(token) / (3600.0 / 1852.0); // Pull as a floating point (in knots, convert to
      m/s)
      }
      }

      }
      }
      void ProcessGPSLine()
      {
         if ((GPSBuffer[1] == 'G') && (GPSBuffer[2] == 'L') && (GPSBuffer[3] == 'G') && (GPSBuffer[4] ==
            'G') && (GPSBuffer[5] == 'A'))
       {
         lcd.print("GLGGA Detected!");
          }

        }
        void readSerialGPS()
       {
         static char receivedGPSChars[MAX_NMEA]; // buffer for received GPS data
       static int ndx = 0; // buffer index
        static boolean newGPSData = false;

        while((gpsSerial.available() > 0) && (newGPSData == false)) // Drop out at each complete line
      {
       char rc = gpsSerial.read();

    Serial.write(rc); // Feed byte from GPS to the console

    if (rc != '\r') { // Terminate line, CR,LF pair
      if (rc == '$') // Resync on leading '$'
        ndx = 0;
      if (rc != '\n') // Don't copy LF
        receivedGPSChars[ndx++] = rc;
      if (ndx >= MAX_NMEA) // Constrain length
        ndx = MAX_NMEA - 1;
      }
       else { // '\r'
      receivedGPSChars[ndx] = '\0'; // Terminate the string
      ndx = 0;
      newGPSData = true;
       }
     } // while
     if (newGPSData) // One new line available
     {
       static boolean gpsAlert = false;

    if (gpsAlert == false)
    {
      lcd.setCursor(0,0);
      lcd.print("GPS:ENABLED");

      gpsAlert = true;
    }
     if (strncmp(receivedGPSChars, "$GPGGA", 6) == 0)
      processGGA(receivedGPSChars);
    else if (strncmp(receivedGPSChars, "$GPGLL", 6) == 0)
      processGLL(receivedGPSChars);
    else if (strncmp(receivedGPSChars, "$GPRMC", 6) == 0)
      processRMC(receivedGPSChars);

    newGPSData = false;
     }
     }
      void setup()
     {
     // Start the Arduino hardware serial port at 9600 baud
     Serial.begin(9600);
     // set up the LCD's number of columns and rows:
      lcd.begin(16, 2);

      pinMode(9, OUTPUT);
      // Start the software serial port at the GPS's default baud
      gpsSerial.begin(GPSBaud);
      }
      void loop()
      {
         readSerialGPS(); // Consume data, process sentences
      }

title: Coding of arduino and ZEDF9P GNSS module

Answers: 0


body:
This is my circuit.
[![enter image description here][1]][1]

This is the code.

        #include "U8glib.h" // include the universal graphcs library

        U8GLIB_SSD1306_128X64 u8g(12, 11, 10, 9, 8);  // initialise a u8g display object

        const uint8_t flux_xbm[] PROGMEM = {
           0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xBF, 0x56, 0x6D, 0xFF, 0xFF, 0xFF, 0xFF,
      0xFF, 0xFF, 0xEF, 0xFB, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x5F, 0x69, 0x92,
      0x6E, 0xE7, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0xC1, 0xFF, 0xFE, 0xFF, 0xFF,
      0xFF, 0x3F, 0x80, 0x01, 0xF5, 0x7E, 0xFF, 0xFF, 0xFF, 0xFB, 0x00, 0xC2,
      0x3F, 0x21, 0xF4, 0xFF, 0xFF, 0xFF, 0x36, 0x6C, 0xBE, 0x7F, 0xFC, 0xFF,
      0xFF, 0xFF, 0x00, 0xC0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x7F, 0x86, 0x61,
      0xDE, 0x4F, 0xFE, 0xFF, 0xFF, 0xFB, 0x64, 0xE4, 0xFF, 0xFF, 0xFF, 0xFF,
      0xFF, 0x3F, 0x20, 0x04, 0xFC, 0x63, 0xFA, 0xFF, 0xFF, 0xFD, 0x24, 0xCD,
      0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x1F, 0x95, 0xA9, 0x7F, 0x08, 0xFC, 0xFF,
      0xFF, 0xF7, 0x27, 0xDA, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xBF, 0x00, 0x00,
      0x04, 0x50, 0xFC, 0xFF, 0xFF, 0xFF, 0xD9, 0xC9, 0xFF, 0xFF, 0xFF, 0xFF,
      0xFF, 0x3F, 0x10, 0x01, 0x21, 0x90, 0xFC, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
      0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x3F, 0x02, 0x84, 0x08, 0x02, 0xFC, 0xFF,
      0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x3F, 0x04, 0x00,
      0x00, 0x28, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
      0xFF, 0x1F, 0x00, 0x00, 0x00, 0x00, 0xF8, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
      0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x3F, 0x00, 0x00, 0x00, 0x00, 0xFC, 0xFF,
      0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x3F, 0x00, 0x00,
      0x00, 0x00, 0xF8, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
      0xFF, 0x1F, 0x00, 0x00, 0x00, 0x00, 0xFC, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
      0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x1F, 0x00, 0x00, 0x00, 0x00, 0xF8, 0xFF,
      0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x3F, 0x00, 0x00,
      0x00, 0x00, 0xF8, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
      0xFF, 0x1F, 0x00, 0x00, 0x80, 0x07, 0xFC, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
      0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x1F, 0x00, 0x00, 0xC0, 0x05, 0xF8, 0xFF,
      0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x1F, 0x00, 0x00,
      0xB8, 0x0F, 0xF8, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
      0xFF, 0x3F, 0x00, 0xE0, 0xFB, 0x1F, 0xFC, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
      0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x1F, 0x00, 0xF0, 0xFF, 0x0F, 0xF8, 0xFF,
      0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x1F, 0x00, 0xBC,
      0xFE, 0x1F, 0xF8, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
      0xFF, 0x3F, 0x00, 0xDF, 0x49, 0x1F, 0xFC, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
      0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x1F, 0x00, 0x4B, 0xA8, 0x1F, 0xF8, 0xFF,
      0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x1F, 0x40, 0x00,
      0x40, 0x7A, 0xFC, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
      0xFF, 0x1F, 0x80, 0x00, 0xA0, 0xFD, 0xF8, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
      0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x3F, 0x40, 0x00, 0x00, 0x7A, 0xFC, 0xFF,
      0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x3F, 0x00, 0x00,
      0xA2, 0xF5, 0xF9, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
      0xFF, 0x1F, 0x70, 0x00, 0x00, 0xF9, 0xFD, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
      0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x1F, 0x30, 0x00, 0xA0, 0xFC, 0xFD, 0xFF,
      0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x1F, 0x00, 0x00,
      0x00, 0xE2, 0xF9, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
      0xFF, 0x3F, 0x10, 0x00, 0x00, 0xD8, 0xFD, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
      0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x1F, 0x00, 0x00, 0xD2, 0xB7, 0xFB, 0xFF,
      0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x1F, 0xD0, 0x02,
      0x60, 0x5F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
      0xFF, 0x1F, 0x08, 0x35, 0xF4, 0xF9, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
      0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x1F, 0x40, 0x08, 0xDC, 0xD4, 0xFF, 0xFF,
      0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x1F, 0x20, 0x36,
      0x16, 0x9F, 0xFD, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
      0xFF, 0x1F, 0x42, 0xEC, 0xB7, 0xAB, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
      0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x1F, 0xA0, 0x67, 0xAB, 0xBC, 0xFF, 0xFF,
      0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x1F, 0x40, 0x66,
      0xB4, 0x6A, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
      0xFF, 0x3F, 0x34, 0x49, 0x06, 0x95, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
      0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xDF, 0x0B, 0x20, 0x5C, 0x0A, 0xFF, 0xFF,
      0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x1D, 0x10,
      0x5C, 0xE4, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
      0xFF, 0xFF, 0x1E, 0x08, 0xB8, 0xD5, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
      0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x4A, 0x15, 0x64, 0x29, 0xFF, 0xFF,
      0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x7F, 0x0E, 0x10,
      0xAA, 0x91, 0xFD, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
      0xFF, 0x7F, 0x9E, 0x00, 0xB4, 0x6C, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
      0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x7F, 0x0F, 0x12, 0xED, 0x6A, 0xFF, 0xFF,
      0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x3F, 0x1F, 0x80,
      0x7E, 0x99, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
      0xFF, 0x9F, 0x5F, 0x14, 0xBA, 0xD4, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
      0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xBF, 0x5F, 0x41, 0xE4, 0x69, 0xFE, 0xFF,
      0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x9F, 0xBF, 0x05,
      0xAA, 0x7B, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
      0xFF, 0x3F, 0x7F, 0xD8, 0xF9, 0xD5, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
      0xF7, 0xFF, 0xFF, 0xFF, 0xFF, 0xBF, 0xFF, 0x2A, 0xFA, 0xA8, 0xFD, 0xFF,
      0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x7F, 0xFF, 0x4D,
      0x6A, 0xB7, 0xF9, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
      0xFF, 0xFF, 0xFF, 0x27, 0x90, 0xDA, 0xFC, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
      0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xAF, 0xFF, 0xFE, 0xF8, 0xFF,
      0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x8F,
      0x6A, 0x7F, 0xF8, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
      0xFF, 0xFF, 0xFF, 0xF7, 0x7F, 0xF7, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
      0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0x43, 0xD8, 0x7D, 0xFF, 0xDF,
      0xBF, 0x9B, 0xEF, 0xFF, 0x5F, 0xAF, 0xAF, 0xAF, 0xAF, 0xAF, 0xBF, 0x43,
      0x88, 0xFF, 0xFF, 0xFF, 0xFB, 0xFF, 0xFF, 0xFE, 0xFB, 0xFF, 0xFF, 0xFF,
      0xFF, 0xFF, 0xEF, 0x41, 0xA8, 0xFF, 0x5D, 0x77, 0x9F, 0xBF, 0xE6, 0x77,
      0xFF, 0xFB, 0xFB, 0xFB, 0xFB, 0xFB, 0xF7, 0xEF, 0xFE, 0xEF, 0xFF, 0xFF,
      0xFF, 0xDB, 0xBF, 0xF7
        };

        void setup(void) {
        }

        void loop(void) {
          u8g.drawXBMP( 0, 0, 128, 64, flux_xbm); // send the xbm image to the display, specifying position and size
          while (1==1) {} // set the loop to only run once
        }

The image that it holds in XBM is this.

[![enter image description here][2]][2]
The output is this.
[![enter image description here][3]][3]
What is it that I am doing wrong?
Edit 1- As reported by user timemage. The xbm array was 64x128 instead of 128x64 I have changed the image added a more simpler one but that still does not solve the problem,

  [1]: https://i.stack.imgur.com/r0Z7L.png
  [2]: https://i.stack.imgur.com/GHqgL.jpg
  [3]: https://i.stack.imgur.com/8Dagd.jpg

title: SSD1306 shows static when I try to display an XBM image

Answers: 1

body:
NOTE: This refers to an problem in the initial posting.  The question **has since been edited**.  This may be deleted later.
<hr>

One problem, perhaps *the* problem, is that your given image appears to be 64x128 rather than 128x64:

[![rendered XBM][1]][1]

That said, I'm not sure exactly why the screen is showing precisely what it does.

When you do get this showing in the correct resolution, I expect you'll be a bit unimpressed with the result though.

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


body:
I'm trying to work with the FastLed libraries and i'm controlling a Led Stip via a WEMOS D1 MINI based on the ESP8266, what I'm trying to achieve is to jump from fastled animation to another one..those animations are inside a While loop as shown in the code, so , i thought to just read again from the serial in order to change an integer to exit those while loop, but for some reason is not working as expected. Anyone can help me to uderstand?

    CRGB leds[NUM_LEDS];
    int incomingByte = 0;
    int exit = 0;
    void setup() {
        Serial.begin(115200);
        delay( 1000 );
        FastLED.addLeds<LED_TYPE, LED_PIN, COLOR_ORDER>(leds, NUM_LEDS).setCorrection( TypicalLEDStrip );
        FastLED.setBrightness(  BRIGHTNESS );
    }

    void loop()
    {
     while (Serial.available()>0)
     {
       Serial.write("Serial.available");
        incomingByte = Serial.read();

        switch (incomingByte)
      {
        case '1':
       GreenYellow();
       break;

        case '2':
       Sparkle();
       break;
      }
     }
    }

    void Sparkle() {
     while(exit = 0){
      int Pixel = random(NUM_LEDS);
      setPixel(Pixel,random(255),random(255),random(255));
      FastLED.show();
      delay(50);
      setPixel(Pixel,0,0,0);
      if(Serial.available()>0){
       incomingByte = Serial.read();
       if(incomingByte != '2'){
        exit = 1;
       }
      }
     }
      }
    }
    void GreenYellow()
    {
      for(int x =0; x< NUM_LEDS/2; x++){
        leds[x]= CRGB::Green;
      }

      for(int x =NUM_LEDS/2; x< NUM_LEDS; x++){
        leds[x]= CRGB::Yellow;
      }
      FastLED.show();
    }

    void setPixel(int Pixel, byte red, byte green, byte blue)
    {
       leds[Pixel].r = red;
       leds[Pixel].g = green;
       leds[Pixel].b = blue;
       FastLED.show();
    }
    void setAll(byte red, byte green, byte blue) {
      for(int i = 0; i < NUM_LEDS; i++ ) {
        setPixel(i, red, green, blue);
      }
      FastLED.show();
    }

**Bonus question:** I read that there is no thread programming on the ESP2866 via the Arduino IDE, am I right?

title: Why I can't exit this while loop by reading from the Serial?

Answers: 1

body:
The problem is that you check inside the two functions `Sparkle` and `GreenYellow` for another serial byte. Then when it's unequal, you move back to the `while` loop where you wait for the next serial byte, but I think you need to use the same one to decide to go to the correct function instead of waiting for a next serial byte.

Probably the easiest is to not read serial in the `while` loop but check the `incomingByte` global variable  (containing the last read byte, and e.g. 1 initially), and ONLY in the two functions set that global variable. Then, when returning to the `while` loop, you check that global variable to jump to the correct function.

So you make a `setup` function that sets the global variable to 1 (or you do it in the initialization itself):

    int incomingByte = 1; // Start with GreenYellow

Then, in the `loop` function, you use:

    void loop()
    {
           switch (incomingByte)
            {
              case '1':
                GreenYellow();
                break;

              case '2':
                Sparkle();
                break;
            }
    }

If you don't want to start in either one, then use 3 values (0, 1, 2), and ONLY in the `loop` function read the Serial byte, but don't read it in the functions.
This way it's a bit more cleaner as it separates the LED functionality with the Serial functionality.

The result (using the last method), results in the following code (compiles, not checked).

Comments:

- Used an enumeration for the mode
- Split functionality of serial data, processing the mode and RGB routines
- I added some initialization lines (i.e. constants) to make it compile.

    ```
    #include <FastLED.h>

    #define NUM_LEDS 60 // number of led present in your strip
    #define LED_PIN 6
    #define BRIGHTNESS 100

    enum EMode
    {
      ModeNone,
      ModeSparkle,
      ModeGreenYellow
    };

    CRGB leds[NUM_LEDS];
    EMode mode;

    void ParseSerialData();
    void ProcessMode();
    void GreenYellow();
    void Sparkle();
    void setPixel(int Pixel, byte red, byte green, byte blue);

    void setup()
    {
        Serial.begin(115200);
        delay( 1000 );
        FastLED.addLeds<WS2811, LED_PIN, EOrder::RGB>(leds, NUM_LEDS).setCorrection( TypicalLEDStrip );
        FastLED.setBrightness(  BRIGHTNESS );
        mode = EMode::ModeNone;
    }

    void loop()
    {
      ParseSerialData();
      ProcessMode();
    }

    void ParseSerialData()
    {
      while (Serial.available() > 0)
      {
        Serial.write("Serial.available");
        char incomingByte = Serial.read();

        switch (incomingByte)
        {
        case '1':
          mode = EMode::ModeGreenYellow;
          break;

        case '2':
          mode = EMode::ModeSparkle;
          break;

        default:
          // Ignore
          break;
        }
      }
    }

    void ProcessMode()
    {
      switch (mode)
      {
      case EMode::ModeNone:
        // Do nothing
        break;

      case EMode::ModeGreenYellow:
        GreenYellow();
        break;

      case EMode::ModeSparkle:
        Sparkle();
        break;

      default:
        // Ignore
        break;
      }
    }

    void Sparkle()
    {
        int Pixel = random(NUM_LEDS);
        setPixel(Pixel,random(255),random(255),random(255));
        FastLED.show();
        delay(50);
        setPixel(Pixel,0,0,0);
    }

    void GreenYellow()
    {
      for(int x =0; x< NUM_LEDS/2; x++)
      {
        leds[x]= CRGB::Green;
      }

      for(int x =NUM_LEDS/2; x< NUM_LEDS; x++)
      {
        leds[x]= CRGB::Yellow;
      }
      FastLED.show();
    }

    void setPixel(int Pixel, byte red, byte green, byte blue)
    {
       leds[Pixel].r = red;
       leds[Pixel].g = green;
       leds[Pixel].b = blue;
       FastLED.show();
    }

    void setAll(byte red, byte green, byte blue)
    {
      for(int i = 0; i < NUM_LEDS; i++ ) {
        setPixel(i, red, green, blue);
      }
      FastLED.show();
    }
    ```


body:
I have an Arduino Nano 33 IoT and have used it for a good time now. I was using it when the antenna snapped off. Is there any way to fix it by either an external antenna or some other method? I tried to just hold the antenna in place as I tried to connect to wifi but it failed to connect.

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

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

title: Arduino nano IoT antenna broke

Answers: 2

body:
The problem that I see in the photo is that the pads from the PCB are pulled off and attached to the antenna. So now there is nothing to solder the antenna back to.

While it's possible to rework this with some solder rework tools, I suspect you don't have those.  There is really not much else you can do but replace the Nano with a new one.  You should still be able to use this one for an application that doesn't need WiFi.

It looks like the two active leads (the two in the upper right-hand side of the green module may be those) are still intact.  If you have a small tip soldering iron and a steady hand you may be able to put a tiny drop of solder on both of them and then resolder the antenna to them.  You could support the antenna with some silicone caulk or other non-conductive adhesive after you get it attached.

Keep in mind, that this is tricky to solder by hand but there is little to lose since that part of the module is not non-functional anyway.

body:
It is still possible to get work. I see the copper pads have been pulled off so you need to use extra amount of solder and hopefully it attaches to the remained copper wire.

My case is even worse because the antenna is lost, so I have to remade one.
[![enter image description here][1]][1]

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

And it works.


body: i want to use volte and current sensors (ZMPT101B and ACS712) on node MCU these sensors are analog but node mcu has on analog pin can i use digital D0 pin for voltage sensor?

title: using a digital pin on node mcu as an analog

Answers: 0


body:
I want to provide a delay in the following iteration reading so that the sensor can read the condition after the pump starts.

```c++
void loop() {
  //-------------Fungsi Read sensor-----------
  // sensorAll();

  hasilec = (ppmcensor - inputec);
  ph = (phcensor - inputph);

  //  hasilec = random(-200, 0) / 100.0;
  //  ph = random(-200, 200) / 100.0;

  //  ph = -180/100.0;
  //  hasilec = -1.2;

  unsigned long now = millis();

  Serial.print("pH    ");
  Serial.print(ph);
  Serial.print("  ");
  Serial.print("EC ");
  Serial.print(hasilec);
  Serial.println("");
  Serial.print(ph); Serial.print(" ");
  Serial.print(hasilec); Serial.print(" ");
  Serial.println(" ");

  //  delay (500000);

  fuzzy->setInput(2, hasilec);
  fuzzy->setInput(1, ph);
  fuzzy->fuzzify();

  float pompa01 = fuzzy->defuzzify(1);//pHDOWN
  float pompa02 = fuzzy->defuzzify(2);//pHUP
  float pompa03 = fuzzy->defuzzify(3);//ABMIX

  Serial.println("Result= ");
  Serial.println("");
  Serial.print(" Pompa1 pHDOWN: ");
  Serial.println(pompa01);
  Serial.print(" pompa2 phUP  : ");
  Serial.println(pompa02);
  Serial.print(" pompa3 ABMIX : ");
  Serial.println(pompa03);
  Serial.println("");
  Serial.println("");
  Serial.println("");

  delay (2000);

  long int pompa1 = pompa01 * 1000;
  long int pompa2 = pompa02 * 1000;
  long int pompa3 = pompa03 * 1000;

  pump_periods[0] = pompa1; //PHdown
  pump_periods[1] = pompa2; //PHup
  pump_periods[2] = pompa3; //ABMIX

  for (int i = 0; i < jml_pump; i++) {
    if (now - pump_last_actuations[i] >= pump_periods[i]) {
      pump_states[i] = (pump_states[i] == LOW) ? HIGH : LOW;
      digitalWrite(pump_pins[i], pump_states[i]);
      pump_last_actuations[i] = now;
    }
  }
}
```

If I put the delay after millis iteration it causes the pump to only turn on based on the delay, not the timer millis. What should I do?

title: How to stop the relay after it is getting on and let the sensor get the result

Answers: 1

body:
If all the pumps have to work for `pump_periods[i]` time on every loop, and you will have a long `delay()` anyway, you could replace the `for` loop with:

```c++
for (int i = 0; i < jml_pump; i++) { // For every pump:
  digitalWrite(pump_pins[i], 1);     // Start pump i
  delay(pump_periods[i]);            // Wait for pump_periods[i] ms
  digitalWrite(pump_pins[i], 0);     // Stop pump i
}
delay(120000);                       // Wait 2 minutes until mixed
```

This will block the loop, but you will have a long delay anyway. The pumps will work sequentially, and not at the same time.

Is that what you want?


body:
I am using an Arduino Mega to display the readings of 4 pots on a Nextion Display as well as store them on an SD Card with a time stamp. I keep getting:

`recvRetCommandFinished err`

on the serial monitor and the display does not update with time.

I have attached my code below:

```c++
#include "Nextion.h"
#include <SPI.h>
#include <SD.h>
#include <Wire.h>
#include "RTClib.h"

RTC_DS1307 rtc;
char daysOfTheWeek[7][12] = {"Sunday","Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"};

// Declare your Nextion objects - Example (page id = 0, component id = 1, component name = "b0")
NexText tDate = NexText(0, 1, "tDate");
NexText tPot1 = NexText(0, 6, "tPot1");
NexText tPot2 = NexText(0,7, "tPot2");
NexText tPot3 = NexText(0, 8, "tPot3");
NexText tPot4 = NexText(0, 9, "tPot4");

File myFile;

void setup(void) {
  Serial1.begin(9600);
  // Open serial communications and wait for port to open:
  Serial.begin(9600);

  if (! rtc.begin()) {
    Serial.println("Couldn't find RTC");
    while (1);
  }

  if (! rtc.isrunning()) {
    Serial.println("RTC is NOT running!");
    // following line sets the RTC to the date & time this sketch was compiled
    rtc.adjust(DateTime(F(__DATE__), F(__TIME__)));
    // This line sets the RTC with an explicit date & time, for example to set
    // January 21, 2014 at 3am you would call:
    //rtc.adjust(DateTime(2016, 11, 19, 19, 45, 0));   // <----------------------SET TIME AND DATE: YYYY,MM,DD,HH,MM,SS
  }

  delay(100);

  // You might need to change NexConfig.h file in your ITEADLIB_Arduino_Nextion folder
  // Set the baudrate which is for debug and communicate with Nextion screen
  nexInit();

  SPI.begin();

  int pot1 = 0;
  int pot2 = 0;
  int pot3 = 0;
  int pot4 = 0;

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

  Serial.print("Initializing SD card...");
  if (!SD.begin(53)) {
    Serial.println("initialization failed!");
    while (1);
  }
  Serial.println("initialization done.");

  // open the file. note that only one file can be open at a time,
  // so you have to close this one before opening another.
}

void loop(void) {
  myFile = SD.open("testpot1.csv", FILE_WRITE);
  // if the file opened okay, write to it:
  if (myFile) {
    Serial.print("Writing to testpot1.txt...");

    while(1) {
      DateTime now = rtc.now();
      myFile = SD.open("testpot1.csv ", FILE_WRITE);
      int pot1 = analogRead(A0);
      int pot2 = analogRead(A1);
      int pot3 = analogRead(A2);
      int pot4 = analogRead(A3);
      myFile.print(now.hour());
      myFile.print(":");
      myFile.print(now.minute());
      myFile.print(",");

      myFile.println(pot1);
      myFile.println(",");
      tPot1.setText(pot1);

      myFile.println(pot2);
      myFile.println(",");
      tPot2.setText(pot2);

      myFile.println(pot3);
      myFile.println(",");
      tPot3.setText(pot3);

      myFile.println(pot4);
      myFile.println(",");
      tPot4.setText(pot4);

      Serial.print(pot1);
      Serial.print(",");
      Serial.print(pot2);
      Serial.print(",");
      Serial.print(pot3);
      Serial.print(",");
      Serial.print(pot4);
      Serial.print(",");

      delay(2000);
      myFile.close();
    }
  } else {
    // if the file didn't open, print an error:
    Serial.println("error opening test.txt");
  }
}
```

[![Image of the serial Monitor][1]][1]

How do I get the pot values on my display? Any help or tips would be helpful!

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

title: Nextion Display not getting updated data

Answers: 2

body:
`recvRetCommandFinished err` means something is wrong with the serial communication between the Arduino and the Nextion display; it is what [`recvRetCommandFinished()`][1] prints when there is an error.

Check if you are using the right pins (TX1 and RX1 for Serial1) for the serial connection to the display, the actual connections you made (RX1 to TX, TX1 to RX), the baud rate, and the cable.

  [1]: https://github.com/itead/Segnix/blob/master/libraries/itead_Nextion/NexHardware.cpp#L189

body: I changed the text components to number components on the Nextion GUI Editor. That worked as I primarily wanted to show numerical readings from the pot.


body:
As the question says: I'm building a circuit to run a DC motor whenever motion is detected by a motion sensor. Now as this image suggests:

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

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

I need a diode + resistor + transistor to get this thing to turn with an Arduino, but I can do the same with a battery and connecting each of the terminals to the + and - of the battery. I understand this might be for speed control? Or turning the motor different ways?

But if I just need it to spin at 100%, would all this be needed?

I tried hooking up the motor directly with a resistor to the 5 V + GND of the board while it was on, but no joy. I am (obviously) doing something wrong but I want to use this problem as a way to learn circuits better.

title: Why is it I need transistors and resistors to turn a DC motor with an Arduino but I can connect it directly to a battery?

Answers: 1

body:
If you want the motor to rotate continuously, without using PWM, and without switching the motor on and off from the Arduino, you can connect the motor straight to 5 V and ground. If you then add a large resistor like you tried, not enough current will pass through the motor to rotate it; in the image the resistor is there to limit the current into the transistor, not to limit the current into the motor.

You can't connect a motor directly to an IO pin because an IO pin can only deliver about 20 mA, which isn't enough for a motor. So, if you want to control a motor from an IO pin, you need a transistor as a switch and you operate that transistor from the IO pin. The transistor does the heavy lifting and switches the larger current the motor needs. The resistor is there to limit the current into the transistor.

Note that it is generally better to wire a motor directly to a 5 V power source and not to the 5 V pin on the Arduino, as the current you can get from that pin is limited; it will do for small motors, though, if they don't pull more than, let's be safe, about 300 mA. In other words, it is preferred not to use the Arduino 5 V pin as a power source, but to use a 5 V power source directly.

Also note that you always need the diode across the motor, however you wire it. It keeps inductive spikes away from the rest of your circuit.


body: I have a motion sensor (used for camera trapping) that sends a signal to the camera to trigger the shutter. I am trying to use Arduino to turn on lights for 10 seconds by getting the signal from the motion sensor. I know there are ways to use motion sensor that can be used with Arduino. However, I need to know how I can detect a signal coming from the sensor to feed it to Arduino. I have tried connecting the cable from the sensor to A0, wrote a simple code to print the value of A0 but the serial monitor of Arduino shows nothing.

title: detecting signal coming from another motion sensor that triggers camera's shutter

Answers: 2

body:
Sorry I am typing this here coz I don't have enough rep to comment. Anywho, most of the motion sensors involve PIR tech, so the best way is to connect your PIR Signal pin from your sensor to any analog pin of your arduino and test the kind of signal you're getting when the environment is idle and when movement is detected, Keep in mind of the region that the sensor covers too (ROI). That will tell you some things,

- If the sensor works or not.
- If the sensor value is analog or digital
- If the sensor is active high or low
- Trial and error on the actual ROI

After all that you can write your code around it.

body:
Almost all camera shutter cables are simple switches. They are an open circuit until you want to press the shutter, and then the switch closes. There is no voltage out of the shutter release, and so nothing for an analog pin to detect.

Many cameras have a shutter half-press switch that activates the light meter/auto-focus, and then a second switch that closes the shutter.

For a simple RCA plug shutter release or mono 3.5 mm plug shutter release, it's probably just a simple single pole switch. Wire one wire from the shutter release to a digital pin, and the other wire to ground. Set the pin to INPUT_PULLUP, and wait for it to go LOW. When it goes LOW the shutter is being pressed.

Be aware that a modulated IR shutter trap will be a little slow. It probably won't catch subjects like birds flying at high speed until the bird has moved past the point where the trap is pointed. For that you would want a laser beam and a fast phototransistor. Those can be fast enough and accurate enough to measure the speed of a bullet. (Although you need to read port registers directly in order to get fast enough response for that. `DigitalRead()` is too slow.)


body:
I am using a Quectel L80-R GPS Module coupled with an Arduino UNO to read and log my car's coordinates and speed. I am currently using TinyGPS++ library which works okay. It does spell out coordinates and speed but with some inaccuracies and delays. After some literature review I realized that NeoGPS library might be a better option. I found a [thread][1] over stackexchange where a code block is provided written by [slash-dev][2] who most possibly is the writer of NeoGPS library. However, when I am trying to compile the code, I get the following error
```'class gps_fix' has no member named 'lat'``` .I can not get rid of the issue even tough I've tried a whole bunch of workarounds.

  [1]: https://arduino.stackexchange.com/questions/22873/neo-6m-gps-speed
  [2]: https://arduino.stackexchange.com/users/14737/slash-dev

title: Speed data logging using arduino and GPS module

Answers: 1

body:
According to the [NeoGPS documentation for the gps_fix class][1], it looks like `.lat` and `.lon` are no longer part of the `gps_fix` class.

It looks like instead you will have to use `.latitudeL` and `.longitudeL` for high precision (Long Integer scaled by 10,000,000) GPS coordinates.

The solution would be to replace `fix.lat` in your code with `fix.latitudeL` and `fix.lon` with `fix.longitudeL`.

  [1]: https://github.com/SlashDevin/NeoGPS/blob/master/extras/doc/Data Model.md


body:
I have interfaced a height sensor and a weight sensor. The I2C address of the height and weight sensors are 0x29 and 0x2A respectively. I have merged the example of both the sensors.

This is the first time I am working with I2C and need help on this.

Do let me know about any mistakes or any sort of example which can help me to learn coding different I2C addresses, sensors, and interfacing.

```c++
#include <Wire.h>
#include "SparkFun_VL53L1X.h"
#include "SparkFun_Qwiic_Scale_NAU7802_Arduino_Library.h"

NAU7802 myScale;
SFEVL53L1X distanceSensor;

//Optional interrupt and shutdown pins.
#define SHUTDOWN_PIN 2
#define INTERRUPT_PIN 3

void setup() {
  Serial.begin(9600);
  Wire.begin(0x2A);
  if (myScale.begin() == false) {
    Serial.println("Scale not detected. Please check wiring. Freezing...");
    while (1);
  }
  Serial.println("Scale detected!");

  Wire.begin(0x29);
  if (distanceSensor.begin() != 0) { //Begin returns 0 on a good init
    Serial.println("Sensor failed to begin. Please check wiring. Freezing...");
    while (1) ;
  }
  Serial.println("Sensor online!");
}

// put your setup code here, to run once:

void loop() {
  distanceSensor.startRanging(); //Write configuration bytes to initiate measurement
  while (!distanceSensor.checkForDataReady()) {
    delay(1);
  }
  int distance = distanceSensor.getDistance(); //Get the result of the measurement from the sensor
  distanceSensor.clearInterrupt();
  distanceSensor.stopRanging();

  Serial.print("Distance(mm): ");
  Serial.print(distance);

  float distanceInches = distance * 0.0393701;
  float distanceFeet = distanceInches / 12.0;

  Serial.print("\tDistance(ft): ");
  Serial.print(distanceFeet, 2);

  Serial.println();
  if(myScale.available() == true) {
    long currentReading = myScale.getReading();
    Serial.print("Reading: ");
    Serial.println(currentReading);
  }
}
```

title: Looking to interface height and weight sensor based on I2C Protocol

Answers: 0


body:
I have the following serial message that I'm receiving from an ESP32 running GRBL:

```
<Idle|MPos:158.500,0.000,0.000|FS:0,0|Pn:H|Ov:100,100,100|SD:0.21,/instruction.nc>
```

I want to check the value after `SD:` which in this case would be `0.21`.
It is a value that represents the percentage of a file being read, so values between 100.00 and 0.00 are being sent.

My guess is to look for the `SD:` in the string and then read all characters until the `,` but I can't really find a way to realize that.

I found the ```startsWith()``` and the ```substring()```function that are able to look for a set of characters in a string, but it seems like they can only check a set amount of characters which in this case doesn't work as ```0.00``` is 4 characters and ```100.00``` is 6 characters.

Any help is much appreciated!!

title: Search for a certain combination of strings in serial and read the following characters until another set character stops the search

Answers: 1

body:
Firstly you should really be working with a C string (`char *`) instead of a `String` object, otherwise you will be massively fragmenting your heap with the string manipulations to come.

Once you have your data in a C string (char array) you can use `strtok_r` to split the string on the `|` character, then for each substring further split it on the `:`.  You need the `_r` variant of `strtok` to make it "re-entrant" so you can have two tokenizations at once nested.

For example (untested):
```c++
char *data = "<Idle|MPos:158.500,0.000,0.000|FS:0,0|Pn:H|Ov:100,100,100|SD:0.21,/instruction.nc>";
char *pair; // Pointer to a K/V pair
char *pairptr = data; // Pointer for outer strtok

// Split the string on the first |
pair = strtok_r(data, "|", &pairptr);

// While we have a K/V pair
while (pair) {
    char *kvptr = pair;
    // Split the substring into two parts on the colon
    char *key = strtok_r(pair, ":", &kvptr);
    char *val = strtok_r(NULL, ":", &kvptr);
    if (val) { // If we split the data correctly:
        if (strcmp(key, "SD") == 0) { // If the key is "SD" then
            Serial.print("SD data: ");
            Serial.println(val);
        }
    }
    // Get the next string portion
    pair = strtok_r(NULL, "|", &pairptr);
}
```

Once you have your `val` you can further split that down on commas in the same way as it's been split on the colon.


body:
Does anyone know why these 4 resistors are there (attachment)? It seems like they are useless since connected in a loop to GND.
Full schematics here: https://store.arduino.cc/arduino-due

[![Arduino Due shematics][1]][1]

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

title: Are these GND connected resistors on the Arduino Due redundant?

Answers: 1

body:
Yes, they are redundant. They are elements of resistor arrays (multiple resistors in one package) that aren't used. They have just connected all unused pins of those packages to ground.

If you want to know why they would have unused elements, it's all to do with optimizing the manufacturing process. If you have, say some 100k arrays elsewhere in your design and you want to have maybe one or two other 100k resistors elsewhere, rather than adding another component of a discrete 100k resistor it's cheaper to use a 100k array and not use some of the elements. One of the factors in the cost of pick-and-place operations is the number of different components. By keeping the number of component types to a minimum they keep the manufacture costs to a minimum.


body:
I need to send a pulse to an Arduino at **every one hour**. I don't need day, month, year etc. I just want a pulse from DS3231 at every 1 hour **through the square wave pin**.

https://github.com/NorthernWidget/DS3231
**I have included this library** but I can't anyhow understand how to generate an pulse at each hour using this library. Is it possible?

My requirement is simple. I need a pulse at my Arduino interrupt pin at each hour.

    #include <DS3231.h>
    #include <Wire.h>

    void setup()
    {
      Wire.begin();
      EICRA |= 0b00000011;
      EIMSK |= 0b00000001;
      sei();
     // No clue on how to setup DS3231 for getting a pulse at each hour
    }
    ISR(INT0_vect)
    {
      // This function will be executed in each hour
    }
    void loop(){}

title: Problem understanding how to program DS3231 RTC

Answers: 2

body:
See the documentation at:

[DTC3231 Library Documentation][1]

Where there is the section on alarm bits and setting alarms:

      // Alarm functions

      void getA1Time(byte& A1Day, byte& A1Hour, byte& A1Minute, byte& A1Second, byte& AlarmBits, bool& A1Dy, bool& A1h12, bool& A1PM);
    /* Retrieves everything you could want to know about alarm
     * one.
     * A1Dy true makes the alarm go on A1Day = Day of Week,
     * A1Dy false makes the alarm go on A1Day = Date of month.
     *
     * byte AlarmBits sets the behavior of the alarms:
     * Dy A1M4 A1M3 A1M2 A1M1 Rate
     * X 1  1  1  1  Once per second
     * X 1  1  1  0  Alarm when seconds match
     * X 1  1  0  0  Alarm when min, sec match
     * X 1  0  0  0  Alarm when hour, min, sec match
     * 0 0  0  0  0  Alarm when date, h, m, s match
     * 1 0  0  0  0  Alarm when DoW, h, m, s match
     *
     * Dy A2M4 A2M3 A2M2 Rate
     * X 1  1  1  Once per minute (at seconds = 00)
     * X 1  1  0  Alarm when minutes match
     * X 1  0  0  Alarm when hours and minutes match
     * 0 0  0  0  Alarm when date, hour, min match
     * 1 0  0  0  Alarm when DoW, hour, min match
     */
      void getA2Time(byte& A2Day, byte& A2Hour, byte& A2Minute, byte& AlarmBits, bool& A2Dy, bool& A2h12, bool& A2PM);
       // Same as getA1Time();, but A2 only goes on seconds == 00.
      void setA1Time(byte A1Day, byte A1Hour, byte A1Minute, byte A1Second, byte AlarmBits, bool A1Dy, bool A1h12, bool A1PM);
       // Set the details for Alarm 1
      void setA2Time(byte A2Day, byte A2Hour, byte A2Minute, byte AlarmBits, bool A2Dy, bool A2h12, bool A2PM);
       // Set the details for Alarm 2
      void turnOnAlarm(byte Alarm);
       // Enables alarm 1 or 2 and the external interrupt pin.
       // If Alarm != 1, it assumes Alarm == 2.
      void turnOffAlarm(byte Alarm);
       // Disables alarm 1 or 2 (default is 2 if Alarm != 1);
       // and leaves the interrupt pin alone.
      bool checkAlarmEnabled(byte Alarm);
       // Returns T/F to indicate whether the requested alarm is
       // enabled. Defaults to 2 if Alarm != 1.
      bool checkIfAlarm(byte Alarm);
       // Checks whether the indicated alarm (1 or 2, 2 default);
       // has been activated.

**UPDATE:**

Based on your comment:

> I checked that too. The example was too complicated.

You need to spend some time gaining a familiarity with some of the basic Arduino and AVR functions.  To make this work you're going to not only need to understand how to talk to the RTC via I2C but also how to enable and respond to a pin interrupt in the AVR.  You have the ISR function there but you have not done anything to enable any interrupt source.

  [1]: https://github.com/NorthernWidget/DS3231/blob/master/DS3231.h

body:
DS3231 address is 104. Instead of using that large complicated header, send simple frame.

For 1 sec pulse the frame will be :
S 208 A 14 A 0 P

N.B. Here address is 7 bit value 104. And a extra bit for R/W operation.

In the Arduino wire library,  you don’t need to include the R/W bit. So,just write 104.
For hourly Alam set the INT bit of control register and send simple frame like this.
Don't make things complicated using the header.


body:
I am trying to send a sequence of commands from a PC to a Mega. The Mega in turn controls 2 signal generators (AD9833's).

The sequences can vary in length but always have the same format:

1) A start byte of 255
2) The length of the sequence
3) Elements of the sequence: Channel 0: MSB, LSB & waveform, Channel 1: MSB, LSB & waveform

The PC side code:

    import serial
    import struct

    usbport    = 'COM3'
    ser        = serial.Serial(usbport, 9600, timeout=1)

    def sendSequence(seq):

        ''' Send a sequence of frequencies along with waveform '''

        # Start byte & sequence length
        ser.write(struct.pack('>B', 255))
        ser.write(struct.pack('>B', len(seq)))

        for s in seq:

            print(s)
            MSB, LSB = (s[0] & 0xFFFF).to_bytes(2, 'big')     # Split frequency to send
            ser.write(struct.pack('>B', MSB))
            ser.write(struct.pack('>B', LSB))
            ser.write(struct.pack('>B', s[1]))                # Waveform

            combined = ((MSB & 0xFF) << 8) | (LSB & 0xFF)
            print(combined)

    sendSequence([[1000, 0], [1000, 0], [2000, 0], [1000, 0], [2000, 0], [2000, 0]])
    ser.close()

On the Arduino side:

    #include <SPI.h>

    // Set up Serial data variables
    byte freq_MSB;
    byte freq_LSB;
    int startbyte;
    unsigned long freq_seq_ch_0[16];
    int wave_seq_ch_0[16];
    unsigned long freq_seq_ch_1[16];
    int wave_seq_ch_1[16];
    int wave_select = 0;
    int seq_length;
    long f_2;
    long f_1;

    const int SINE     = 0x2000;                // Define AD9833's waveform register value.
    const int SQUARE   = 0x2028;                // When we update the frequency, we need to
    const int TRIANGLE = 0x2002;                // define the waveform when we end writing.
    int wave           = SINE;

    const float refFreq = 25000000.0;           // On-board crystal reference frequency

    const int FSYNCA = 53;                       // Standard SPI pins for the AD9833 waveform generator.
    const int FSYNCB = 49;
    const int CLK    = 52;

    unsigned long pause     = 5000;
    unsigned long freq      = 1000;              // Set initial frequency.
    int i;

    void setup() {

      // Set slave ocntrol pins
      pinMode(FSYNCA, OUTPUT);
      pinMode(FSYNCB, OUTPUT);
      digitalWrite(FSYNCA, HIGH);
      digitalWrite(FSYNCB, HIGH);

      // Set up SPI
      SPI.begin();
      SPI.setDataMode(SPI_MODE2);
      delay(50);

      // Set up AD9833s
      AD9833reset();                                   // Reset AD9833 module after power-up.
      delay(50);
      AD9833setFrequency(freq, SINE, FSYNCA);          // Set the frequency and Sine Wave output
      AD9833setFrequency(freq, SINE, FSYNCB);

      // Open the serial connection, 9600 baud
      Serial.begin(9600);
    }

    void loop() {

       // Wait for serial input
      if (Serial.available()) {

        startbyte = Serial.read();              // Read the first byte
        if (startbyte == 255) {
          seq_length = Serial.read();

          for (i = 0; i < seq_length; i++) {

            // Channel 0
            freq_MSB = Serial.read();
            freq_LSB = Serial.read();
            f_2 = (long)freq_MSB << 8;
            f_1 = (long)freq_LSB;
            freq_seq_ch_0[i] = f_2 | f_1;
            wave_select = Serial.read();
            switch (wave_select) {
              case 0:
                wave_seq_ch_0[i] = SINE;
                break;
              case 1:
                wave_seq_ch_0[i] = TRIANGLE;
                break;
              case 2:
                wave_seq_ch_0[i] = SQUARE;
                break;
              }

            // Channel 1
            freq_MSB = Serial.read();
            freq_LSB = Serial.read();
            f_2 = (long)freq_MSB << 8;
            f_1 = (long)freq_LSB;
            freq_seq_ch_1[i] = f_2 | f_1;
            wave_select = Serial.read();
            switch (wave_select) {
              case 0:
                wave_seq_ch_1[i] = SINE;
                break;
              case 1:
                wave_seq_ch_1[i] = TRIANGLE;
                break;
              case 2:
                wave_seq_ch_1[i] = SQUARE;
                break;
              }
          }

          // Send sequence to signal generators
          for (i = 0; i < seq_length; i++) {
            AD9833setFrequency(freq_seq_ch_0[i], wave_seq_ch_0[i], FSYNCA);
            AD9833setFrequency(freq_seq_ch_1[i], wave_seq_ch_1[i], FSYNCB);
            delay(3000);
          }

        }

      }
    }

    // AD9833 documentation advises a 'Reset' on first applying power.
    void AD9833reset() {
      WriteRegister(0x100, FSYNCA);   // Write '1' to AD9833 Control register bit D8.
      delay(10);
      WriteRegister(0x100, FSYNCB);
      delay(10);
    }

    // Set the frequency and waveform registers in the AD9833.
    void AD9833setFrequency(long frequency, int Waveform, int channel) {

      long FreqWord = (frequency * pow(2, 28)) / refFreq;

      int MSB = (int)((FreqWord & 0xFFFC000) >> 14);    //Only lower 14 bits are used for data
      int LSB = (int)(FreqWord & 0x3FFF);

      //Set control bits 15 ande 14 to 0 and 1, respectively, for frequency register 0
      LSB |= 0x4000;
      MSB |= 0x4000;

      WriteRegister(0x2100, channel);
      WriteRegister(LSB, channel);                  // Write lower 16 bits to AD9833 registers
      WriteRegister(MSB, channel);                  // Write upper 16 bits to AD9833 registers.
      WriteRegister(0xC000, channel);               // Phase register
      WriteRegister(Waveform, channel);             // Exit & Reset to SINE, SQUARE or TRIANGLE

    }

    void WriteRegister(int dat, int channel) {

      // Display and AD9833 use different SPI MODES so it has to be set for the AD9833 here.
      //SPI.setDataMode(SPI_MODE2);

      digitalWrite(channel, LOW);           // Set FSYNC low before writing to AD9833 registers
      delayMicroseconds(10);              // Give AD9833 time to get ready to receive data.

      SPI.transfer(highByte(dat));        // Each AD9833 register is 32 bits wide and each 16
      SPI.transfer(lowByte(dat));         // bits has to be transferred as 2 x 8-bit bytes.

      digitalWrite(channel, HIGH);          //Write done. Set FSYNC high
    }

My problem is that this does NOTHING. No matter what sequence I send the output of the signal generators never deviates from the set up defaults.

The generators do work & I have managed to control them via serial before but in that case I knew exactly how much information would be in the serial buffer before I read it in but in this case the sequence length isn't known a priori.

Is this a serial issue?

title: Sending variable length sequence via serial from PC to Mega

Answers: 1

body:
The main issue here is, that you are reading data, that might not be received yet. This:

    if (Serial.available()) {

will check if there is **any** data in the Serial buffer. As the code runs rather fast and communication over Serial at 9600 baud is relatively slow, this very well might be true, when not your complete message was received. So you might have received the start byte, but the rest of the data is still being transmitted. In that case `Serial.read()` will return `-1`.

With Serial (UART) the transmission happens with individual bytes, not in big chucks. You need to only read data, that is really received.

As you don't know the sequence length beforehand I would suggest 2 different ways:

1. You can wait for 2 bytes being in the Serial buffer (start byte and length) and then again wait, until enough further bytes are in the Serial buffer (as you now have the length of the sequence).

2. You can rebuild your code, so that it just places the data in an extra buffer, until you have received enough data (which you need to check via the received length byte). Then, when you have received the full message, you process it and then clear the buffer, waiting for a new message.


body:
A friend has told me I shouldn't rely on functions because, during execution, they occupy a significant amount of RAM.

Is that true or, if it isn't, what's the maximum suggested level of function nesting at runtime?

title: RAM cost of entering functions

Answers: 2

body:
> A friend has told me I shouldn't rely on functions because, during execution, they occupy a significant amount of RAM.

I wouldn't say "significant", but *some* RAM is used, yes.

Every time a function is called any registers used in the execution of that function are placed onto the stack. Also some parameters to the function may be passed on the stack (depending on the ABI for the architecture you're using). Further, any local variables used inside the function also go on the stack.

These are only temporary allocations and are released again when the function exits.

Depending on your program the "call stack" can be insignificant compared to the local variables.

> what's the maximum suggested level of function nesting at runtime?

Low enough that you don't run out of memory. When you have plenty of memory then your call stack is irrelevant. When you only have a couple of hundred bytes, or a hardware stack (like on the low-end PIC microcontrollers) with a limited depth, then keeping your program flatter can be better.

The main reason for flattening a program is usually for execution speed rather than for memory use.

body:
I guess avoiding functions may have been relevant with dumb compilers, a
few decades ago. Compilers today are pretty good at optimizing and,
since recently, the Arduino environment enables “link time
optimization”. This means the optimizer can see the whole program at
once, which enables:

- function inlining across compilation units (and the optimizer does
  this pretty aggressively)
- saving, in the function prologue, only the registers that really need
  to be saved.

In most cases, the “optimal” size for a function is whatever size
optimizes the readability of the code. In the rare cases where you would
need to merge a function into its callers for performance purposes, you
can qualify the function as

```c++
inline __attribute__((always_inline))
```

But this only makes sense after you disassembled the program and noticed the
compiler did not make the right optimization choices. A quite infrequent
situation.


body:
I've got Debian 10 as OS and for a Project, I need my arduino to always be connected as /dev/ttyUSB0, not any other ttyUSB-number, and I need it to be connected with the 0777 rights for a script to work.

I've read some things about udev, but nothing I tried yet worked.

I tried creating

/etc/udev/rules.d/51-my_usb_device

with the content

SUBSYSTEM=="tty", MODE="0777", KERNELS=="ttyUSB0"

but it does not work, even after reboot (like nothing changed). I must admit though that I do not really understand udev.

How to do this?

title: How to get arduino to always be connected as /dev/ttyUSB0 and with chmod 0777?

Answers: 1

body:
Have you considered not trying to force ttyUSB0 but instead creating a symlink to whatever tty is assigned? Your software then just uses the symlink.

A problem with forcing a particular tty is what if you boot without the Arduino but another device is attached? You then need to convince the other device to skip ttyUSB0.

If you would consider a symlink then something like:

```
ACTION=="add", KERNEL=="ttyUSB*", ATTRS{idVendor}=="1a86", ATTRS{idProduct}=="7523", SYMLINK+="arduino"
```

might get you started. Check the VID and PID using `lsusb` or similar. To set permissions as well you can use e.g. `MODE="0777"` as you already have.

There is an example at https://wiki.debian.org/udev that might give more background.