body:
Recently I've been working on an automatic dog feeder dispenser (that dispenses by turning a screw attached to a stepper motor). Currently I have a Nema 17 connected to an L298N stepper driver which is connected to Arduino pins 9-12 and a DS1307 RTC connected to analog pins A4 and A5 (I would have a picture but the wiring is all over the place). I would like to connect a 16x2 LCD screen (with a potentiometer already on the back and 4 connecting pins) but from everything I've seen online, it also uses analog pins A4 and A5 which are occupied by the RTC. How would I go about connecting the LCD?

    #include <LiquidCrystal_I2C.h>
    #include <Wire.h>
    #include <RTClib.h>
    #include <SoftwareSerial.h>
    #include <Stepper.h>

    RTC_DS1307 rtc;
    LiquidCrystal_I2C lcd(0x3F , 16 , 2);
    Stepper myStepper(200 , 9 , 10 , 11 , 12);

    void setup() {
      lcd.init();
      lcd.print("yes");
      Wire.begin();
      Serial.begin(9600);
      rtc.adjust(DateTime(2021 , 7 , 15 , 3 , 23 , 0));
      myStepper.setSpeed(100);
    }

    void loop() {
      DateTime now = rtc.now();
      Serial.print(now.hour());
      Serial.print(":");
      Serial.print(now.minute());
      Serial.print(":");
      Serial.print(now.second());
      Serial.println(" ");

      lcd.print(now.hour());
      lcd.print(":");
      lcd.print(now.minute());
      lcd.print(":");
      lcd.print(now.second());
      lcd.println(" ");

      if ((now.hour() == 7 and now.minute() == 0 and now.second() == 0)) {
        myStepper.step(1000);

    }
      delay(1000);

    }

title: Connecting an LCD when Pins A4 and A5 are Occupied

Answers: 2

body:
As mentioned in the comments: Your LCD and the RTC both use the I2C bus for communication. That bus is designed to have many devices simultaneously connected. For this to work every slave device on the bus (the Arduino is the master device, which has no address) has to have a unique address. In your code you write, that the LCD is on address `0x3F`. The RTC DS1307 is `0b1101000` or `0x68` (same value in binary or hexadecimal representation) (see [the DS1307 datasheet][1], page 12).

So you can connect  both devices to the same pins, as the communication interface there already supports that. The pins A4 and A5 are the I2C pins of the Arduino, so you need to connect them there for using the Arduinos I2C hardware.

  [1]: https://datasheets.maximintegrated.com/en/ds/DS1307.pdf

body:
Here are my 2 cents.
As the other answer suggests, you can always use the same I2C lines for devices. The devices will be differentiated via an I2C address. I have compiled one example based on your code. [Here is the link][1] to the simulation

**The code is below**

    #include <Wire.h>
    #include "LiquidCrystal_I2C.h"
    #include <RTClib.h>

    RTC_DS1307 rtc;

    LiquidCrystal_I2C lcd(0x27, 16, 2);

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

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

      lcd.init();
      lcd.backlight();
      lcd.print("yes");
    }

    void loop() {
      DateTime now = rtc.now();
      Serial.print(now.hour());
      Serial.print(":");
      Serial.print(now.minute());
      Serial.print(":");
      Serial.print(now.second());
      Serial.println(" ");

      lcd.setCursor( 0,0);
      lcd.print(now.hour());
      lcd.print(":");
      lcd.print(now.minute());
      lcd.print(":");
      lcd.print(now.second());

      if ((now.hour() == 7 and now.minute() == 0 and now.second() == 0)) {
        // myStepper.step(1000);
      }

      delay(1000);
    }

As you can see, I2C lines are shared between the RTC module and the LC display module.

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

  [1]: https://wokwi.com/arduino/projects/306847788434457154
  [2]: https://i.stack.imgur.com/B9tXN.gif


body:
I have an Arduino UNO. When I connect an MQ-9 sensor or an ESP8266MOD WiFi chip, the LCD backlight drops that it doesn't display anything, the red LEDs on the Arduino board dims, and the voltage regulator begins to get hot.

I am using a 12V -- 1.5A DC supply to power the Arduino as the USB port only works for uploading sketches, it doesn't even power the Arduino when nothing is connected. What could be wrong?

NOTE: When I unplug the gas sensor, the Arduino board LEDs get brighter and the LCD too, it works fine with some other sensors like an LM35 or a flame sensor.

title: Arduino UNO voltage supply reduces when I add more sensors

Answers: 3

body:
The [MQ-9][1] has a heating preparation cycle that draws more than a third of a watt which is more power than the Arduino can supply via a pin if I remember correctly. Have you taken that into allowance? You can design the heater power to be triggered by the Arduino without overloading the pin (e.g, using a transistor).

See https://electronics.stackexchange.com/questions/67092/how-much-current-can-i-draw-from-the-arduinos-pins

If your circuit already allows for the above it could also be a bad/shorted sensor? You could test it’s resistance with a multimeter and compare it to the data sheet.

  [1]: http://www.haoyuelectronics.com/Attachment/MQ-9/MQ9.pdf

body:
You are overloading the Arduinos voltage regulator.

The Arduino uses a linear voltage regulator, which dissipates the excess voltages as heat.The higher the provided voltage, the lesser current you can draw from it (since it can only handle a specific power dissipation without a heatsink and power is voltage * current). If you have a genuine Arduino, the voltage regulator will go into thermal emergency shutdown, if you completely overload it. Most Arduino clones use a cheaper regulator, which will just burn out and possibly destroy the Arduino.

So if you require quite an amount of current (like the MQ-9 due to its heating element), you should buy an extra voltage regulator, in best case a switching "buck" regulator (since they are way more efficient than linear regulators). For example there are many rather cheap boards with a switching regulator, which take 12V and output a variable voltage controlled via a small potentiometer (which you can trim for 5V output).

> the USB port only works for uploading sketches, it doesn't even power the arduino when nothing is connected.

Then most likely you have already overloaded the diode, that is in the USB power path (for protecting the PCs USB port and helping with supply voltage selection). If the diode were fried and failed open, then the connection from USB positive power to 5V rail on the Arduino is no longer there. A genuine Arduino Uno should also have a polyfuse in the USB line, which can save you from drawing too much current. It should connect again, after you removed the devices, that draw too much power.

body:
You are using a lot more power than an arduino pin can supply. The gas sensor takes a lot of power which the arduino's pin supply of 5v and 200mA MAX cannot tolerate. So I would suggest you power the gas sensor using ur 12v Powersupply by creating a simple potential divider, using a buck converter or simply one of those cheap 7805 regulators. For any other power related queries you can refer this excellent article by [BILL][1] from Dronebot Workshop. Good Luck!!

  [1]: https://dronebotworkshop.com/powering-your-projects/


body:
I'm struggling to establish a link between two Arduino Nano using nRF24L01 (the module that contains PA and LNA). I assume I made a coding mistake (May be in the setup method?), and I need help in finding it.
I’m using the **gettingStarted** example from the TMRh20 V1.4.1 RF24 library, with slight modifications in the addressing and error messaging. The sketch contains the code for both the transmitter and the receiver, and the selection is done by the ROLE flag in compile time.

Hardware:
1. I'm using home-designed PCB. For this setup only the Arduino and RF24 modules are assembled.
2. Power:
  a. The RF24 is fed by the 3.3V output of the Arduino.
  b. There is a 47uF cap to filter the power.
  c. The power traces length is about 20mm, and 1.2 mm thick of 1oz copper.
3. Measurements
  a. The setup method verifies that the RF24 module is connected to the SPI bus and reacts to the commands. I verified this test by removing and inserting a module. It works.
  b. When the transmitter was running at repetition rate of 1 cycle per second, I used an oscilloscope to measure on the power line of the RF24 module a ripple of 50mV over DC level of 3.25V (per the data sheet the minimum supply voltage is 1.9V).
3. The setup method verifies explicitly that the RF24 module is connected to the SPI bus and reacts to the commands.

Debugging:

 1. To begin with, the message ** “Transmission failed or timed out” **
    was issued.
 2. When I added the line “radio.setAutoAck(false)” to the setup method, the error message was changed into ** “Transmission succeeded; retransmission failed” **. This is odd because I had to explicitly specify a mode that the chip should be in by default.
 3. I replaced both module in both sides to brand new units, to no avail.
 4. I added to the library’s ** write ** function a print of the status register. It reflects transmission success (see below).

Currently the transmitter messages are as follows (the line numbers were added for the notes):
1 Start loop - TX station
2 WRITE TP 3 - TX OK: status=2E
3 Time to transmit = 960 us.
4 Transmission succeeded; transmitted: 0.08
5 Back transmission failed

Notes:
1. Lines 1, 3, 4 and 5 are issued by the main loop.
2. Line 2 is the WRITE printout.
a. Bit 5 of the status is the TX_DS flag, which signify that the TX FIFO status. Active means that the packet was transmitted successfully.
b. Bits 3:1 mean that RX FIFO is empty.
3. Line 4 – printout of the transmitted payload. The number is increased in every loop by 0.01.
4. Lines 5 tells us that the nothing was received from the other side (the receiver reports that he received nothing).

My problem is that either the transmitter doesn't transmit (low probability) or there is a mismatch between the stations. I assume I made a coding mistake (May be in the setup method?), and I’d appreciate any help in finding it.

Or, should I add voltage regulator to increase the 3.25V to 3.3V?

        #include <SPI.h>
    #include "RF24.h"
    // instantiate an object for the nRF24L01 transceiver
    RF24 radio(9, 10);           // using pin 9 for CE, pin 10 for CSN
    uint32_t address[2] = {0x123456, 0x654321};
    byte role = 1;
    float payload = 0.0;
    uint16_t counter = 0;
    int terminationTimer;
    /***********************************************************/
    void setup()
    {
      Serial.begin(9600);
      while (!Serial) ;
      Serial.println("Starting...");

    // initialize the transceiver on the SPI bus
      radio.begin();
    // Modification - the installed library doesn't
    // return flag. Instead, check the SPI bus by
    // changing register contents
      radio.setPALevel(RF24_PA_HIGH);        // RF24_PA_MAX is default.
      bool paError = !radio.isChipConnected() | (radio.getPALevel() != RF24_PA_HIGH);
      radio.setPALevel(RF24_PA_MIN);
      paError |= (radio.getPALevel() != RF24_PA_MIN);
      if(paError)
      {
        Serial.println("Radio HW error");
        while (true) ;                // Halt
      }
      Serial.print("radio role = ");
      Serial.println(role);
      radio.setRetries(15,15);
      radio.setAutoAck(false);

      if(role == 1)
      {
        radio.openWritingPipe(address[1]);    // always uses pipe 0
        radio.openReadingPipe(1, address[0]); // pipe 1 for
        radio.stopListening();                // put radio in TX mode
      }
      else
      {
        radio.openWritingPipe(address[0]);    // always uses pipe 0
        radio.openReadingPipe(1, address[1]); // using pipe 1
        radio.startListening();               // put radio in RX mode
      }
      terminationTimer = millis();
    //Serial.println("TP C");
    } // setup
    /****************************************************************/
    void loop()
    {
    //Serial.println("TP D - start loop; role = " + String(role));
    //delay(1000);
      if (role == 1)
      {
    Serial.println("\nStart loop - TX station");
     // This device is a TX node
        unsigned long start_timer = micros();            // start the timer
        bool report = radio.write(&payload, sizeof(float)); // transmit & save the result
        uint32_t end_timer = micros();              // end the timer
        if (report)
        {
    // All the code in this block is designed for testing only
          Serial.print(("Time to transmit = "));
          Serial.print(end_timer - start_timer); // print the timer
          Serial.println((" us."));
          radio.startListening();               // put radio in RX mode
          Serial.print("Transmission succeeded; transmitted: ");
          Serial.println(String(payload));
          Serial.print("Back transmission ");
          int tDelay = millis();
          while(((millis() - tDelay) < 250) && !radio.available()){}
          if(radio.available())
          {
            float pl;
            radio.read(&pl, sizeof(float));  // fetch payload from FIFO
            Serial.print("succeeded. Retransmitted: ");
            Serial.println(pl);
          }
          else
            Serial.println("failed");
          radio.stopListening();             // put radio in TX mode
          payload += 0.01;                   // increment float payload
        }
        else Serial.println(("Transmission failed or timed out")); // payload was not delivered
    // to make this example readable in the serial monitor
        delay(1000);  // slow transmissions down to 1 per second
      }
      else
      {
    Serial.println("\nStart loop - RX station");
    // This device is a RX node
        uint8_t pipe = 0;
        if (radio.available(/*&pipe*/))   // is there a payload? get the pipe number that recieved it
        {
          uint8_t bytes;
          bytes = sizeof(float);         // get the size of the payload
          radio.read(&payload, bytes);   // fetch payload from FIFO
    // The rest of the code in this block is for debugging
          radio.stopListening();          // put radio in TX mode
          delay(10);
          Serial.print("Received ");
          Serial.print(bytes);          // print the size of the payload
          Serial.print((" bytes on pipe "));
          Serial.print(pipe);             // print the pipe number
          Serial.print((": "));
          Serial.print(payload);
          if(radio.write(&payload, bytes))
            Serial.print("; back transmission succeeded.");
          else
            Serial.println("; back transmission failed");
          radio.startListening();          // put radio in RX mode
        }
        else
        {
          Serial.println("no receive");
          delay(700);
        }
      } // role
    /*
      if((millis() - terminationTimer) > 10000)
      {
        Serial.println(("Halt"));
          while(true){}
      }
    */
    } // loop

title: No communication between two stations that include Arduino Nano and nRF24L01

Answers: 0


body:
I have no experience about serial communications, with that being said; I have two circuits isolated from each other and each have a ATMEGA8 reading a voltage on their ADC.

I want one of them to send ADC data to another without having a common ground. I know that I can do it with a Bluetooth or Wi-Fi "module" but I'm looking for an easier way, like maybe with an optocoupler but again I'm not aware of the limits.

- What's the cheapest and simplest way to do this? and basically how it's done?

There's a lot of information about making two Arduinos talk to each other but I couldn't find much information/documentation on isolated communications.

title: How to send data from one Arduino to another isolated?

Answers: 1

body:
[Consolidating an answer from the comments]

A wired connection using Optical isolation (aka [Optocouplers][1]) is the recommended way to solve this problem.

There are tutorials available online regarding optical isolation (e.g., https://www.electronics-tutorials.ws/blog/optocoupler.html; https://bestengineeringprojects.com/interfacing-optocoupler-with-arduino/).

One (of many) possible [example][2] circuit was noted as:
[![OptoIsolator FTDI Circuit][3]][3]

  [1]: https://en.wikipedia.org/wiki/Opto-isolator
  [2]: https://github.com/TaaraLabs/OptoIsolatorFTDI
  [3]: https://i.stack.imgur.com/R66iX.png


body:
max30100 i2c sensor gives heartrate and spo2 reading in serial and also can show values in lcd display. I want to show it's indication via LED.

If SpO2 value <94 , it will turn on Red led in digital pin 4

If SpO2 value >=94, it will urn on Green led in digital pin 5

Here **pox.getSpO2()** gives the SpO2 value.

How can I use this value to toggle between two digital pin. I understand it's easier to read analog pin value for toggling but I am searching for guidelines how I2C values can be use for this condition.

Thank you.

Here is the minimalistic code of SpO2

    #include <Wire.h>
    #include "MAX30100_PulseOximeter.h"
    #define REPORTING_PERIOD_MS     1000

    PulseOximeter pox;
    uint32_t tsLastReport = 0;

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

        Serial.print("Initializing pulse oximeter..");

        if (!pox.begin()) {
            Serial.println("FAILED");
            for(;;);
        } else {
            Serial.println("SUCCESS");
        }
    }

    void loop()
    {

        pox.update();

        if (millis() - tsLastReport > REPORTING_PERIOD_MS) {
            Serial.print("SpO2:");
            Serial.print(pox.getSpO2());
            Serial.println("%");

            tsLastReport = millis();
        }
    }

title: Using MAX30100 SpO2 value to turn on LED

Answers: 1

body:
You've done all the hard work already by setting the sensor up and managing to read from it.

I'd define a constant for the SpO2 threshold near the top, and convenient names for the pins:

    const uint8_t SpO2_threshold = 94;  // percent
    const uint8_t red_pin = 4;
    const uint8_t green_pin = 5;

Then set the pins to output mode in the `setup()` as usual. (Maybe set them both HIGH (or LOW) too in there, to indicate that no reading has been done yet.)

In the loop, inside the reporting section, simply grab the value and toggle the pins:

    ...
    uint8_t spo2 = pox.getSpO2();
    // Print it out to serial if needed, then:
    if (spo2 < SpO2_threshold) {
      digitalWrite(green_pin, LOW);
      digitalWrite(red_pin, HIGH);
    } else {
      digitalWrite(red_pin, LOW);
      digitalWrite(green_pin, HIGH);
    }

---

A more involved version that pulses one LED (short on time, variable off time) depending on the value read from the sensor. It uses the same technique as the sensor reading timing (the one used in the "blink without delay" example).

Sensor readings are clamped (any value at or below `spo2_min` will result in the fasted blink time, over `spo2_max` the slowest). Then that range is mapped to a range of led off times. Don't use the values in this example, I'm not a medical doctor :-)

    // pin mapping
    const uint8_t led_pin = LED_BUILTIN;

    // sensor readings (%)
    const int spo2_min = 85;
    const int spo2_max = 100;

    // led timings (ms)
    const unsigned long led_off_min = 50;
    const unsigned long led_off_max = 5000;

    unsigned long led_off_time = led_off_max; // variable off time
    const unsigned long led_on_time = 50;     // fixed, short on time

    // sensor reading timing (ms)
    const unsigned long sensor_interval = 1000;

    // led state
    uint8_t led_state = LOW;

    // "timer" state
    unsigned long last_reading = 0;
    unsigned long last_led_toggle = 0;

    void setup() {
      pinMode(led_pin, OUTPUT);
      digitalWrite(led_pin, led_state);

      Serial.begin(9600);

      Serial.print("Initializing pulse oximeter..");
      if (!pox.begin()) {
        Serial.println("FAILED");
        for (;;);
      } else {
        Serial.println("SUCCESS");
      }
    }

    void loop() {
      pox.update();
      unsigned long current_millis = millis();

      /* sensor reading "timer" */
      if (current_millis - last_reading >= sensor_interval)
      {
        last_reading = current_millis;

        int spo2 = pox.getSpO2();

        // clamp reading to expected range
        int clamped = constrain(spo2, spo2_min, spo2_max);
        // map to off time range
        led_off_time = map(clamped,
                           spo2_min, spo2_max,
                           led_off_min, led_off_max);

        char buff[128];
        sprintf_P(buff, PSTR("reading: %d (%%) -> interval: %lu (ms)"),
                  spo2, led_off_time);
        Serial.println(buff);
      }

      /* led toggling "timers" */
      unsigned long led_elapsed = current_millis - last_led_toggle;

      if ((led_state == LOW) && (led_elapsed >= led_off_time))
      {
        last_led_toggle = current_millis;
        led_state = HIGH;
        digitalWrite(led_pin, led_state);
      }
      else if ((led_state == HIGH) && (led_elapsed >= led_on_time))
      {
        last_led_toggle = current_millis;
        led_state = LOW;
        digitalWrite(led_pin, led_state);
      }

    }


body:
I am trying to compare the string of data which I am receiving from the MQTT broker. If I receive the keyword faster I want to print "increase motor speed" and when I get slower keyword or any other keyword, I want to print "decrease motor speed". I am not sure how to store the data I receive from mqttClient.read()and then store it in string to then compare it
Below is the snippet of the code where I have added it and it seems not to work correctly in my case. can you look at it and let me know what is the mistake?
````
while (mqttClient.available()) {
Serial.print((char)mqttClient.read());
String ipstring= String("(char)mqttClient.read()");
String fast ="faster";
if((char)mqttClient.read()==fast)
{
Serial.println("increase motor speed");}
else
{
Serial.println("decrease motor speed");
}*
}
````

I have also attached the code for reference.
Thank you!

````
/*
  Azure IoT Hub NB

  This sketch securely connects to an Azure IoT Hub using MQTT over NB IoT/LTE Cat M1.
  It uses a private key stored in the ATECC508A and a self signed public
  certificate for SSL/TLS authetication.

  It publishes a message every 5 seconds to "devices/{deviceId}/messages/events/" topic
  and subscribes to messages on the "devices/{deviceId}/messages/devicebound/#"
  topic.

  The circuit:
  - MKR NB 1500 board
  - Antenna
  - SIM card with a data plan
  - LiPo battery

  The following tutorial on Arduino Project Hub can be used
  to setup your Azure account and the MKR board:

  https://create.arduino.cc/projecthub/Arduino_Genuino/securely-connecting-an-arduino-nb-1500-to-azure-iot-hub-af6470

  This example code is in the public domain.
*/

#include <ArduinoBearSSL.h>
#include <ArduinoECCX08.h>
#include <utility/ECCX08SelfSignedCert.h>
#include <ArduinoMqttClient.h>
#include <MKRNB.h>

#include "arduino_secrets.h"
int sensorValue;

/////// Enter your sensitive data in arduino_secrets.h
const char pinnumber[]   = SECRET_PINNUMBER;
const char broker[]      = SECRET_BROKER;
String     deviceId      = SECRET_DEVICE_ID;

NB nbAccess;
GPRS gprs;

NBClient      nbClient;            // Used for the TCP socket connection
BearSSLClient sslClient(nbClient); // Used for SSL/TLS connection, integrates with ECC508
MqttClient    mqttClient(sslClient);

unsigned long lastMillis = 0;

void setup() {
  Serial.begin(9600);
  while (!Serial);

  if (!ECCX08.begin()) {
    Serial.println("No ECCX08 present!");
    while (1);
  }

  // reconstruct the self signed cert
  ECCX08SelfSignedCert.beginReconstruction(0, 8);
  ECCX08SelfSignedCert.setCommonName(ECCX08.serialNumber());
  ECCX08SelfSignedCert.endReconstruction();

  // Set a callback to get the current time
  // used to validate the servers certificate
  ArduinoBearSSL.onGetTime(getTime);

  // Set the ECCX08 slot to use for the private key
  // and the accompanying public certificate for it
  sslClient.setEccSlot(0, ECCX08SelfSignedCert.bytes(), ECCX08SelfSignedCert.length());

  // Set the client id used for MQTT as the device id
  mqttClient.setId(deviceId);

  // Set the username to "<broker>/<device id>/api-version=2018-06-30" and empty password
  String username;

  username += broker;
  username += "/";
  username += deviceId;
  username += "/api-version=2018-06-30";

  mqttClient.setUsernamePassword(username, "");

  // Set the message callback, this function is
  // called when the MQTTClient receives a message
  mqttClient.onMessage(onMessageReceived);
}

void loop() {
  if (nbAccess.status() != NB_READY || gprs.status() != GPRS_READY) {
    connectNB();
  }

  if (!mqttClient.connected()) {
    // MQTT client is disconnected, connect
    connectMQTT();
  }

  // poll for new MQTT messages and send keep alives
  mqttClient.poll();

  // publish a message roughly every 5 seconds.
  if (millis() - lastMillis > 5000) {
    lastMillis = millis();

    publishMessage();
  }
}

unsigned long getTime() {
  // get the current time from the cellular module
  return nbAccess.getTime();
}

void connectNB() {
  Serial.println("Attempting to connect to the cellular network");

  while ((nbAccess.begin(pinnumber) != NB_READY) ||
         (gprs.attachGPRS() != GPRS_READY)) {
    // failed, retry
    Serial.print(".");
    delay(1000);
  }

  Serial.println("You're connected to the cellular network");
  Serial.println();
}

void connectMQTT() {
  Serial.print("Attempting to MQTT broker: ");
  Serial.print(broker);
  Serial.println(" ");

  while (!mqttClient.connect(broker, 8883)) {
    // failed, retry
    Serial.print(".");
    Serial.println(mqttClient.connectError());
    delay(5000);
  }
  Serial.println();

  Serial.println("You're connected to the MQTT broker");
  Serial.println();

  // subscribe to a topic
  mqttClient.subscribe("devices/" + deviceId + "/messages/devicebound/#");
}

void publishMessage() {
  Serial.println("Publishing message");

  // send message, the Print interface can be used to set the message contents
  mqttClient.beginMessage("devices/" + deviceId + "/messages/events/");
  mqttClient.print("hello ");
  sensorValue = analogRead(A0);
  mqttClient.println(sensorValue);
  //mqttClient.print(millis());

  mqttClient.endMessage();
}

void onMessageReceived(int messageSize) {
  // we received a message, print out the topic and contents
  Serial.print("Received a message with topic '");
  Serial.print(mqttClient.messageTopic());
  Serial.print("', length ");
  Serial.print(messageSize);
  Serial.println(" bytes:");

  // use the Stream interface to print the contents
  while (mqttClient.available()) {
    Serial.print((char)mqttClient.read());
    String ipstring= String("(char)mqttClient.read()");
    String fast ="faster";
    if((char)mqttClient.read()==fast)
    {
      Serial.println("increase motor speed");}
      else
      {
        Serial.println("decrease motor speed");
        }
  }
  Serial.println();

  Serial.println();
}
````

title: Comparison of a string received from MQTT/Cloud/Arduino

Answers: 1

body:
As I read the comments, I see the project requirements are evolving. The `0 = Off` command structure will severely limit what you can do, but it is a good starting point.

Regarding the first block of code starting with `while (mqttClient.available()) {`, then adding your one digit / char commands idea, I have this test sketch for you to try.

You don't need the `String` object to accomplish your goal. You may have to do something like this though  `input = (char)mqttClient.read()` where the test sketch uses this `input = Serial.read();`.

```lang-c++
char input;

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

void loop(){

  if(Serial.available() > 0){

    input = Serial.read();

    if(input == '0'){
      Serial.println("Turn Off");
    }

    else if(input == '1'){
      Serial.println("Turn On");
    }

    else if(input == '2'){
      Serial.println("Decrease Speed");
    }

    else if(input == '3'){
      Serial.println("Increase Speed");
    }
  }
}

```

To take it a step further, let's say you want to send commands that start with a single letter, then after the letter, the remaining digits, or chars have a purpose, if you want them to. For example, lets say you send the following command `d50`. The `d` could mean decrease speed, and the `50` could mean 50%, 50 steps, etc.

The following test sketch illustrates my point.

```lang-c++
char inputBuffer[64 + 1];

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

void loop(){

  while(Serial.available() > 0){

    Serial.readBytesUntil('\n', inputBuffer, sizeof(inputBuffer));

    if(inputBuffer[0] == 'f'){
      Serial.println("Letter 'f' entered");
    }

    // Letter "r". Everything after the "r" should be digits.
    else if(inputBuffer[0] == 'r'){
      Serial.print("Letter 'r' entered\t");
      // Change the letter "r" to the digit 0 to keep atol() happy.
      inputBuffer[0] = B110000;
      Serial.print("Number entered = ");
      Serial.println(atol(inputBuffer));

      // Your code here that uses the number parsed using atol().

    }

    // Letter "s". Everything after the "s" should have a max
    // length of up to 64 chars long for a 64 + 1 char buffer.
    else if(inputBuffer[0] == 's'){

      // MAX CHARS example with a 64 byte buffer:
      // s123456789a123456789b123456789c123456789d123456789e123456789f + CR + NL
      Serial.print("Letter 's' entered\tText entered = ");

      // Print out the chars in the buffer.
      for(int i = 1; i < strlen(inputBuffer); i++){
        Serial.print(inputBuffer[i]);
      }
      Serial.println();

      // Your code here that uses the char data after the letter "s" is entered.

    }
    memset(inputBuffer, 0, sizeof(inputBuffer));
  }
}

```


body: Hello i want to switch electric door lock (12V, 170mA) with esp32(3.3V). If is it possible I want use tranzistor. I tried to use IRF520, but it only worked with 5V. My sugestion is use 2 tranzistors one would switch 5V to IRF520 which would switch 12V. Can someone pro provide me some schematic, how to solve it? Thanks.

title: How to switch 12V with esp32?

Answers: 2

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

BC549 provides strong pull-down for IRFR5305, which is provides up to +12V at 16A with less than 0.09 Ohm channel resistance.

This circuit works well with ESP8266, I use it in some of my devices.

Don't forget about placing the flyback diode ([EEV Blog][2], [Wiki][3]) in reverse polarity, parallel to the magnet. Place it as close as possible to the magnet!

  [1]: https://i.stack.imgur.com/nLIiv.png
  [2]: https://www.youtube.com/watch?v=hReCPMIcLHg
  [3]: https://en.wikipedia.org/wiki/Flyback_diode

body:
A single, reasonably tough general purpose BJT is all you need here if you really want a simple solution.  The 2N4401 supports up to 600mA of current and has a 40V Vce max.  As long as the solenoid on the door lock has a snubber it doesn't need to be any more complicated than this unless you need isolation or have other constraints.

Note that below I've drawn a relay because it was easy, but you can just as well put your door lock's solenoid coil where the relay is drawn below (they're effectively the same type of device).

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

I have exactly this setup on an ESP8266 controlling a 24V relay and it works great.  I'm using an old 2N2222, which are long since obsolete, but the 2N4401 would do just the same.

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


body:
I'm writing code for a microcontroller project using PlatformIO.

I have a couple of classes that I want to write unit tests for. I've not unit tested with pio before so I'm starting with one of the easier classes. I wrote out the start of my test:

```
#include "PixelRange.h"
#include <unity.h>

void test_forward_incrementation(void)
{
  PixelRange range = PixelRange(1, 5, 10);
  uint8_t currentIndex = range.getCurrentIndex();

  TEST_ASSERT_EQUAL(5, currentIndex);
}

int main(int argc, char **argv)
{
  UNITY_BEGIN();
  RUN_TEST(test_forward_incrementation);
  UNITY_END();
  return 0;
}
```

For my class:
```
#pragma once
#include <Arduino.h>

class PixelRange
{
public:
  PixelRange() {}
  PixelRange(int rows, int startingIndex, int endingIndex);

  void setReverseIteration(bool reverse);
  uint8_t getNextIndex();
  uint8_t getCurrentIndex();

  int getRowCount();
  int getStart();
  int getEnd();

private:
  bool _iterateInReverse = false;
  uint8_t _iteratorIndex = 0;
  int _rowCount;
  int _start;
  int _end;

  uint8_t forwardIteration();
  uint8_t reverseIteration();
};
```

And my `platform.ini` looks like this:
```
[env:adafruit_trinket_m0]
platform = atmelsam
board = adafruit_trinket_m0
framework = arduino
lib_deps = fastled/FastLED@^3.4.0

[env:native]
platform = native
test_ignore = test_embedded

```

I wanted to start by running the test in the native environment, but when I run it I get errors saying that I'm missing the `Arduino.h` file. Even odder, one of the errors is coming from a file that's not even under test.

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

I'm referring to [the calculator example](https://github.com/platformio/platformio-examples/tree/develop/unit-testing/calculator) as far as setup and I don't see anywhere in the desktop test where Arduino.h is mocked.

Anyone have an idea of why this would be failing? Here's [the full project](https://github.com/chris-schmitz/li-light) in case that helps.

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

title: platformio native unit test Arduino.h not found

Answers: 0


body:
I have a simple MG996 servo motor and I am trying to make it move with my Arduino Uno. I tried different ways of wiring but nothing seems to work as fully expected.

For the wiring I followed this video: https://www.youtube.com/watch?v=b_xvu6wWafA and at 9:02 min the guy is showing how the wiring is done. As you can see in my photo, I have done the same thing (as you can see in the "my wiring" picture), with an external battery pack and everything but my code still does not work. No errors or anything, compiles and uploads perfectly. The code I was trying to execute is:

    #include <Servo.h>

    Servo myservo;

    void setup() {
      myservo.attach(8);
    }

    void loop() {
      myservo.write(0);
      delay(1000);
      myservo.write(90);
      delay(1000);
    }

This code is essentially trying to move the servo from 0 to 90 degrees back and forth. The pin is the correct one (#8). The arduino is receiving the right code (because I tried it with exemplary ones).

Important note: One thing I tried, however, was to not even have an external battery pack. Just connect the wires like so but instead of the 2 GNDs, only 1 GND and 1 +5V pin. That way I was able to move the servo only forward but never backwards! And every time I wanted to move it I had to write a higher degree value.

So the question is, is my wiring bad? I must be missing something.

Photos: [![My wiring][1]][1]

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

title: Arduino UNO won't move servo

Answers: 1

body:
You have not connected the supply pin properly.
here is the connection diagram for the standard basic Arduino example
I also verified this on the video you have linked. Connect the 5V and you should be good to go.

https://wokwi.com/arduino/projects/306894988845777472

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

  [1]: https://i.stack.imgur.com/mLQQ5.png
  [2]: https://i.stack.imgur.com/TiTAA.gif


body:
How to power esp32 board [this one][1] with soil humidity sensor that sends data to server via wifi every 30 minutes for something around a year on battery? What battery type and capacity should I use for that? Or is there any better board you would recommend for this pourpouse? The setup will be indoors.

  [1]: https://www.laskarduino.cz/lolin-32-esp-32s-2-4ghz-dual-mode-wifi-bluetooth--cp2102--nabijeni-baterie/

title: ESP32 powered for atleast a year

Answers: 1

body:
Okay, let's do some calculations.

Assume that device sends data for 5 seconds (turn on, connect to the Wi-Fi, and so on) and drains (according to the docs) about 0.2A.

So, it works for 5 (secs) * 48 (turn-on's) / 60 minutes per day for 365 days.

So, it works for 5 * 48 / 3600 hours per day for 365 days.

So, it works about 24 hours per year.

0.2A for 24 hours is 4.8A for 1 hour.

Assume that efficiency of the power regulator is 80%

4.8  - 80 %
X    - 100%

X = 6 A*h

So, take three (to compensate self discharge and have some headroom) standard Li-Ion cells, or mid-size (about 8000 mAh) power bank, and you well be fine.

But you shall add some external clock (powered by own CR2032 cell), that will be turn power regulator and esp-device ON every 30 minutes.


body:
I am trying to run a very simple program to glow LEDs in a certain fashion, I connected 9 LEDs to the GPIOs or digital pins, 2 To 10, via 220 Ohm resistors; when I am running the program it is hanging the Arduino after some time interval and LEDs stops glowing, not sure if it is a hardware issue or some bug in the software/code.

Here is the code:

    int outGPIOsarr[9] = {2,3,4,5,6,7,8,9,10};

    void setup() {

      for(int i=0; i<10; i++)
    pinMode(outGPIOsarr[i], OUTPUT);
    }

    void loop() {

    for(int i=0; i<10; i++)
     {
    digitalWrite(outGPIOsarr[i],HIGH);
    delay(10);
     }

    for(int i=0; i<10; i++)
     {
    digitalWrite(outGPIOsarr[i],LOW);
    delay(10);
     }

    }

title: Arduino Hanging Not sure if software or hardware issue

Answers: 1

body:
This is the UB!

The indexes in array in `C++` counts from `0`;

So, the last index in your array of `9` elements is **`8`**.

All cycles must stop at **`8`**. Yours are stops at `9`.

Access beyond the existing element in the array is the Undefined Behavior - it hangs the MCU.


body:
Well, I'm trying to use a HMI display and this HMI storing datas in separeta addreses. Such as integers addr. is between 0x80000 to 0x9ffff and also for string's addr is between 0 to 0x1ffff.

**At this point I want to make function which is return integer if addr is a integer addr OR it will return string if addr is String addr. is that possible to make two kind of return type for a method.**

I will detect integer or string from addr value like this:

    ????    HMT_SendCMD_ReadVPN16(INT32U Addr)

    if((Addr > 0x00080000) || (Addr < 0x0009FFFF))
        {
            return int (); // at here it call a fonction and it will return integer
        }

    else if(Addr < 0x0001FFFF)
        {
             return String (); // at here it call a fonction and it will return String
        }

title: İs that possible to a function return String OR Int depends on address

Answers: 2

body:
>  is that possible to make two kind of return type for a method

No. Functions are *declared* with a single return type. What is the point anyway of returning a blank string?

You need to redesign.

body:
If the task were to store something different at the given address,

or if you would want to return a String representation of the integer,

you might be able to do so, but Majenko's comment and Nick's response, suggesting a different approach, are better.


body:
I am trying to read input from the serial monitor on my Arduino UNO using the new Arduino IDE 2.0 and send a specific infrared signal depending on the command.

I do this using the following code:

    #include <Arduino.h>

    /*
     * Define macros for input and output pin etc.
     */
    #include "PinDefinitionsAndMore.h"
    #include <IRremote.h>

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

        Serial.begin(115200);
        while(!Serial) ;

        // Just to know which program is running on my Arduino
        Serial.println(F("START " __FILE__ " from " __DATE__ "\r\nUsing library version " VERSION_IRREMOTE));

        /*
         * The IR library setup. That's all!
         */
        IrSender.begin(IR_SEND_PIN, ENABLE_LED_FEEDBACK); // Specify send pin and enable feedback LED at default feedback LED pin

        Serial.print(F("Ready to send IR signals at pin "));
        Serial.println(IR_SEND_PIN);
        Serial.println("Commands: start, stop, links, rechts, heim, max");
    }

    /*
     * Set up the data to be sent.
     * For most protocols, the data is build up with a constant 8 (or 16 byte) address
     * and a variable 8 bit command.
     * There are exceptions like Sony and Denon, which have 5 bit address.
     */
    uint16_t sAddress = 0x5540;
    uint8_t sCommand_Start_Stop = 0x44;
    uint8_t sCommand_Left = 0x44;
    uint8_t sCommand_Right = 0x44;
    uint8_t sCommand_Home = 0x44;
    uint8_t sCommand_Max = 0x44;

    uint8_t sRepeats = 1;

    bool is_running = false;
    String command;

    void loop() {
      if(Serial.available()){
            command = Serial.readStringUntil('\n');

            Serial.print(F("Command received: "));
            Serial.println(command);

            if(command.equals("start")){
                sendIRCommand(sAddress, sCommand_Start_Stop);
                is_running = 1;
            } else if(command.equals("stop")){
                sendIRCommand(sAddress, sCommand_Start_Stop);
                is_running = 0;
            } else if(command.equals("links")){
                sendIRCommand(sAddress, sCommand_Left);
            } else if(command.equals("rechts")){
                sendIRCommand(sAddress, sCommand_Right);
            } else if(command.equals("heim")){
                sendIRCommand(sAddress, sCommand_Home);
            } else if(command.equals("max")){
                sendIRCommand(sAddress, sCommand_Max);
            } else{
                Serial.println("Invalid command!");
            }
        }
    }

    void sendIRCommand(int irAddress, int irCommand) {
      /*
         * Print current send values
         */
        Serial.println();
        Serial.print(F("Send now: address=0x"));
        Serial.print(irAddress, HEX);
        Serial.print(F(" command=0x"));
        Serial.print(irCommand, HEX);
        Serial.println();

        Serial.println(F("Send NEC with 16 bit address"));
        Serial.flush();

        IrSender.sendNEC(irAddress, irCommand, sRepeats);
    }

In the process I encounter the problem that the serial monitor constantly reads unknown characters as alleged inputs, although I don't send anything. Because of the two unknown characters, even the proper commands can't be recognized correctly, which is a big problem. Here is the extract of the serial monitor:

    15:53:42.987 -> START c:\PATH\TO\SCRIPT\command-sender.ino from Aug 16 2021
    15:53:45.093 -> Using library version 3.1.1
    15:53:45.094 -> Ready to send IR signals at pin 3
    15:53:45.096 -> Commands: start, stop, links, rechts, heim, max
    15:53:45.100 -> Command received: ��
    15:53:47.107 -> Invalid command!
    15:53:47.107 -> Command received: ��
    15:53:49.122 -> Invalid comma��
    15:53:49.122 -> Command received: ��
    15:53:50.113 -> Invalid command!
    15:53:50.117 -> Command received: ��
    15:53:52.131 -> Invalid command!
    15:53:52.131 -> Command received: ��
    15:53:54.131 -> Invalid command!
    15:53:54.131 -> Command received: ��
    15:53:56.142 -> Invalid command!
    15:53:56.142 -> Command received: ��
    15:53:57.142 -> Invalid co+���Command received: ��
    15:53:58.147 -> Invalid command!
    15:53:58.147 -> Command received: ��start
    15:53:58.932 -> Invalid command!
    15:53:58.933 -> Command received: ��
    15:54:00.950 -> Invalid command!

I checked the baudrate, use Serial.print and wait in the setup until the serial is initialized before I send data. I use `115200baud` in the serial monitor in the IDE as well as `New Line`. All without success. How can I fix this problem?

Here is the URL for the [PinDefinitionsAndMore.h][1] if this is the root of the problem.

## Update ##

When using VisualStudio Code with the PlatformIO extension, sending the commands works just fine. Here the unknown characters don't show up neither. It almost seems like the problem is related to the Arduino IDE 2.0 in some way.

  [1]: https://github.com/Arduino-IRremote/Arduino-IRremote/blob/master/examples/SimpleSender/PinDefinitionsAndMore.h

title: Serial monitor constantly reads input with unknown characters

Answers: 0


body:
I am trying to get a constant PWM value from the PWM pin based on the user input. For example: the user hits 1, the output PWM value is 100, if it is 2 the output would be 200. This will continue till the user enters a new number.
The issue I am having with my code is when I enter a number, the output of the PWM goes to that value for about a second and then goes back to 0. Can you please let me know what I am missing?

````
// Sketch: Blinking two LEDs by user
int test_pin=2; // declare pin10 as ledpin
int PWMvalue; // variable to store the number of blinks
void setup()
{
  Serial.begin(9600);
}
void loop()
{
  Serial.println("What is the new speed?"); //Prompt User for Input
 while (Serial.available() == 0) {
    // Wait for User to Input Data
  }
  PWMvalue = Serial.parseInt(); //Read the data the user has input

  if (PWMvalue==0)
  {
    analogWrite(test_pin,0);
    }
    else if (PWMvalue==1)
    {
      analogWrite(test_pin,100);
      }
      else if (PWMvalue==2)
    {
      analogWrite(test_pin,200);
      }
      else if (PWMvalue==3)
    {
      analogWrite(test_pin,300);
      }
      else if (PWMvalue==4)
    {
      analogWrite(test_pin,400);
      }
      else if (PWMvalue==5)
    {
      analogWrite(test_pin,500);
      }
      else if (PWMvalue==6)
    {
      analogWrite(test_pin,600);
      }
      else if (PWMvalue==7)
    {
      analogWrite(test_pin,700);
      }
      else if (PWMvalue==8)
    {
      analogWrite(test_pin,800);
      }
      else if (PWMvalue==9)
    {
      analogWrite(test_pin,900);
      }
      else
    {
      analogWrite(test_pin,1023);
      }

  Serial.print("The user has choosen the number:");
  Serial.println(PWMvalue);
  Serial.println(" ");
}
```

title: Getting constant PWM value based on user input from serial monitor

Answers: 1

body:
You wait for user input with a `while (Serial.available() == 0)`, the you read the input with `Serial.parseInt()`. [parseInt][1] will wait a second for digits. It will end on a non digit character or timeout and return the number corresponding to received digits. If no digits were received a 0 is returned.

Serial Monitor has Line end setting. If there is some line ending selected, it will send line ending character(s).

Your waiting loop `while (Serial.available() == 0)` will end on line ending character which followed the number processed in previous loop. `parseInt` will not find a digit so it times out after a second and returns a 0, which causes setting the PWM to 0.

  [1]: https://www.arduino.cc/reference/en/language/functions/communication/serial/parseint/


body:
I have designed and manufactured a PCB which contains an ESP8266 (ESP-WROOM-02D) chip with the serial uart pins connected to a 30pin connector. I made a mistake on the layout (first time designing a PCB), and have the RX (Pin 3) and TX (pin 1) pins connected incorrectly (swapped).

Is there a way to switch these pins in software? There's no nice way to physically modify and I was hoping to not have to have the boards manufactured again if I can avoid it.

Thanks!

title: Swap Serial pins of ESP8266?

Answers: 1

body:
You could potentially still fix this by using `SoftwareSerial`.
Instead of using the hard-wired serial, you can create one in software and use any pins you'd like... Have a look at [this github project](https://github.com/plerup/espsoftwareserial).
This work-around however requires you to have two unused pins to assign to SoftwareSerial.


body:
I'm a newbie to arduino but been programming lots.
I have a project where I would like to output 4 bits to adjacent pins and read 4 bits from another (4) adjacent pins. (Imagine a matrix keyboard application).
To do it in C-C++ would take lots of instructions (and time) but machine code

OUTPUT:
OR (mask) -> output port      ; this clears bits target bits while leaving other bits as they were
AND (newdata) -> output port  ; this sets new data into target bits

INPUT:
port -> register
AND (register) (mask) -> register

Is there a way of implementing this as a call from IDE for instance.
I have come across many systems where multi language components can be compiled into one executable.

If it is not normally done, why not? Is it something that I should avoid for some reason?

Thanks
Dave

title: Parallel I/O - maybe use Machine code function call

Answers: 1

body:
You can manipulate the I/O ports directly from C++ without having to resort to assembly code.

The AVR micro in your Arduino (ATmega328P) has three ports (PORTB, PORTC and PORTD) with eight pins each (Px0, Px1, ... Px7). You control the ports using three 8-bit registers. Each bit in a register represents one physical pin (LSB is pin 0, MSB pin 7):

- DDRx: data direction register. A bit set to "1" corresponds to output mode, "0" to input.
- PORTx: data register. In output mode, "1" sets the port HIGH, "0" sets it LOW. In input mode, controls whether pull-ups are enabled ("1") or not ("0").
- PINx: input and toggle register. Read it to get the status of all eight pins of the port at once. Writing to it toggles (LOW -> HIGH or HIGH -> LOW) the selected pins (e.g. `PINC = 0b00100001;` toggles pins PC0 and PC5).

With an Arduino, you don't have access to all the pins of all the ports. To get the mapping between Arduino pin names and ports, look at any good Arduino pinout reference (e.g. on the [Arduino Uno page](https://store.arduino.cc/arduino-uno-rev3) in the "Documentation" tab). You can see for example that all pins of port D are available as Arduino digital pins D0 to D7 on an Uno for example. The analog pins are from PORTC.

[![Arduino Uno Rev 3 pinout][1]][1]

Macros are provided (by the AVR toolchain) for port and pin names to make things easier.
For example, `PORTB` is an alias for the PORTB register, you can assign to it as if it was a regular C++ variable. `PB5` is the index of pin 5 in port B. So setting port B pin 5 to output without affecting the others can be written as:

    DDRB |= (1 << PB5);

If you wanted to set the 4 lower pins of port D to output, and the 4 others to input, you could:

    DDRD = 0b00001111; // or 0x0f

Here's an example of a minimal blink sketch:

    void setup() {
      // Set PB5 (D13 - builtin led) LOW
      PORTB &= ~(1 << PB5);
      // Set PB5 mode to OUTPUT
      DDRB |= (1 << PB5);
    }

    void loop() {
      delay(1000);
      // toggle PB5
      PINB |= (1 << PB5);
    }

The assembly generated is optimal, single instructions to set or clear a bit in I/O memory:
(See https://arduino.stackexchange.com/questions/21401/see-compiled-assembly-output-visual-micro for how to get it)

    // setup
      PORTB &= ~(1 << PB5);
     1f4:   2d 98           cbi     0x05, 5 ; 5
      DDRB |= (1 << PB5);
     1f6:   25 9a           sbi     0x04, 5 ; 4

    // loop
      PINB |= (1 << PB5);
     246:   1d 9a           sbi     0x03, 5 ; 3

Another example, that blinks a led connected to A3 only when A2 is high:

    void setup() {
      // Set PC2 and PC3 LOW (A2 and A3)
      PORTC &= ~((1 << PC2) | (1 << PC3));
      // Set PC2 to input, PC3 mode to output
      DDRC = (DDRC & ~(1 << PC2)) | (1 << PC3);
    }

    void loop() {
      delay(1000);
      // toggle PC3 only if PC2 is high
      if (PINC & (1 << PC2)) {
        PINC = (1 << PC3);
      }
    }

Again, assembly generated is quite terse:

      if (PINC & (1 << PC2)) {
        PINC = (1 << PC3);
     202:   18 e0           ldi     r17, 0x08       ; 8
     252:   32 99           sbic    0x06, 2 ; 6
     254:   16 b9           out     0x06, r17       ; 6

(The SBIC instruction is fun: skip the next instruction if a bit in I/O memory is clear.)

You can even save the use of that register `r17` by using `PINC |= ...` in this case:

      // toggle PC3 only if PC2 is high
      if (PINC & (1 << PC2)) {
        PINC |= (1 << PC3);
     250:   32 99           sbic    0x06, 2 ; 6
     252:   33 9a           sbi     0x06, 3 ; 6

Of course you can also resort to inline assembly, but that is an art in and of itself, and the syntax a bit peculiar. But for simple things, it is straightforward:

    asm("sbi 0x03, 5;"); // toggle PB5

Some references:

- ATmega328P Datasheet linked from here: [Microchip ATMega328P page](https://www.microchip.com/en-us/product/ATmega328P#document-table). See section 14 "I/O ports", and 36 "Register summary" for the I/O port addresses.
- The [AVR Instruction Set Manual](https://ww1.microchip.com/downloads/en/DeviceDoc/AVR-Instruction-Set-Manual-DS40002198A.pdf) (PDF) if you want to dive into that.
- The [AVR-GCC Inline Assembler Cookbook](https://www.nongnu.org/avr-libc/user-manual/inline_asm.html) for details on using GCC's flavor of inline assembly for AVR

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


body:
I am trying to do OTA over MQTT using update.h library. I am publishing firmware file over MQTT in a specified chunk size. The file is receiving at ESP32 end. I am supplying the received data to ```update.write```. In start ~150 packet are written successfully. But after that update.write started to give error **Wrong Magic Byte**.

Here is the code snippet which I am using inside ESP32

    #include "mqtt_handler.h"
    StaticJsonDocument <256> root;
    uint8_t temp[100] = {0};
    size_t length ;
    void otaHandler(byte *msg, unsigned int len)
    {
    deserializeJson(root,msg);
    String command = root["command"];
    if (command.equals("ota.start"))
    {
        Serial.println("OTA.START via MQTT");
        if (!Update.begin(UPDATE_SIZE_UNKNOWN))
        {
            Update.printError(Serial);
        }
    }
    else if (command.equals("ota.write"))
    {
        Serial.println("OTA.WRITE via MQTT");
        memset(temp, 0, 100);
        length = root["length"];
        String data = root["data"];
        for (int i = 0; i < length; i++)
        {
            temp[i] = data[i];
        }

        Serial.println(data);
        if (Update.write(temp, length) != length)
        {
            Update.printError(Serial);
        }
    }
    else if (command.equals("ota.end"))
    {
        Serial.println("OTA.END via MQTT");
        if (Update.end(true))
        {
            Serial.printf("Update Success \nRebooting...\n");
        }
        else
        {
            Update.printError(Serial);
        }
    }
    else
    {
        Serial.println("Something went worng");
    }
    }
    void callback(char* topic, byte* message, unsigned int length) {
    otaHandler(message,length);
    }

In this code ```callback``` is the method which is called when an MQTT message arrived.This is the relevant code, if required I can share the complete code.

Message send by python application looks like as below:
```
{"command" : "ota.start"}
{"command": "ota.write", "length": length, "data": data})
{"command" : "ota.end"}
```
Below is the snapshot of ```data``` send by Python application in above ota.write message:

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

Below is the snapshot how my firmware file looks like:

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

I am sharing this snapshot to show the data format in which I am publishing firmware file.

Below is the snapshot of serial monitor:
[![enter image description here][3]][3]

Please suggest me if I am missing something on this.

Thanks

  [1]: https://i.stack.imgur.com/hNptB.png
  [2]: https://i.stack.imgur.com/73OBP.png
  [3]: https://i.stack.imgur.com/hrURd.png

title: ESP32 OTA update over MQTT using "update.h"

Answers: 1

body:
You are just throwing an unparseable stream of ASCII decimal representations of the binary data at your code, then writing that ASCII data verbatim to the flash. That can never work.

Instead you need to pick an ASCII representation of your data that is actually parseable (I would suggest sticking to HEX representation and always 2 digits, so represent 0x6 as "06"), then when you receive a packet you must convert the content back into binary before sending it to the Update library.

As it is you take a byte (for example 0xE9) and convert that to ASCII decimal, which is 223. Then you write the 2, 2 and 3 as individual bytes to the flash as ASCII, resulting in 0x32,0x32,0x33 - or printing as decimal in an unparseable stream, 505051.


body: I will be controlling a robot with more than 10 motors which means I'll need 2 buttons each to control moving forward and backward. My controller is an Arduino mega. Is 1 pin = 1 button the best solution here? Or should I use another IC for this?

title: What is the best technique to design a 20 push button circuit

Answers: 5

body:
you can use a so called shift register. One very common one is a 74HC165 shift register (https://playground.arduino.cc/Code/ShiftRegSN74HC165N/).

With one of such IC you can connect 8 buttons, however you can daisy chain max 4 to get 4 * 8 = 32 button inputs, only using 4 digital pins of the Arduino. In your case you would need 3 ICs to get 24 (thus 20) button inputs.

body:
For 20 buttons you can use a Keypad Matrix arrangement (plenty of examples online) where you would use only 9 pins (5 columns of 4 rows is 5+4 pins). It's slightly more involved that simple 1:1 buttons to pins, but thankfully there is a Keypad.h library that takes the hard work out of it for you.

If you want to be able to press multiple buttons at once you need to include diodes in your matrix to prevent "ghosting".

Nick Gammon has a great writeup on it [here](https://www.gammon.com.au/forum/?id=14175).

body:
The example project below can control 16 switches. If you have a membrane keypad with 5 x 4 or 5 x 5 then you can meet your requirement.

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

I will shortly add an example of using shift registers to have multiple inputs (the main use case of shift registers is the same)

[Link][2]
_______________________

Below is the example using **shift registers.** You need three shift registers as @Michael mentioned in his answer. Here is one example where you can control 32 switches maximum. You are only using 3 data pins and two power pins. This is the main application of the shift register. You don't have to do any selection, whenever you read the serial input data, you will automatically get the status of all the 32 switches in one Go.

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

Here is the **code**

    // File : Cascade165.ino
    //
    // Version 1, 5 August 2021, by Koepel
    //     Initial version.
    // Version 2, 5 August 2021, by Koepel
    //     Layout of the wiring made better.
    // Version 3, 13 August 2021, by Koepel
    //     Changed 'SCK' to 'clockPin'.
    //
    // Cascade of four 74HC165 shift-in registers.
    // Only three pins are used on the Arduino board, to read 32 switches.
    //
    // Using the 74HC165 is safe, because a pulse to the Latch pin
    // ('PL' on the 74HC165) will make a new start every time.
    // In case of an error or a wrong clock pulse by noise,
    // it synchronizes the data when inputs are read the next time.
    //
    // Based on:
    //   (1)
    //     Demo sketch to read from a 74HC165 input shift register
    //     by Nick Gammon, https://www.gammon.com.au/forum/?id=11979
    //   (2)
    //     74HC165 Shift register input example
    //     by Uri Shaked, https://wokwi.com/arduino/projects/306031380875182657
    //
    //

    const byte latchPin = 9;        // to latch the inputs into the registers
    const byte clockPin = 13;       // I choose the SCK pin
    const byte dataPin = 12;        // I choose the MISO pin
    uint32_t oldOptionSwitch = 0;   // previous state of all the inputs

    const int pulseWidth = 10;      // pulse width in microseconds

    void setup ()
    {
      Serial.begin( 115200);
      Serial.println( "Turn on and off the switches");
      Serial.println( "Top row is switch 0 (right) to switch 7 (left)");
      Serial.println( "Second row is 8 to 15, and so on");

      pinMode( clockPin, OUTPUT);   // clock signal, idle LOW
      pinMode( latchPin, OUTPUT);   // latch (copy input into registers), idle HIGH
      digitalWrite( latchPin, HIGH);
    }

    void loop ()
    {
      // Give a pulse to the parallel load latch of all 74HC165
      digitalWrite( latchPin, LOW);
      delayMicroseconds( pulseWidth);
      digitalWrite( latchPin, HIGH);

      // Reading one 74HC165 at a time and combining them into a 32 bit variable
      // The last 74HC165 is at the bottom, but the switches start numbering
      // at the top. So the first byte has to be shifted into the highest place.
      uint32_t optionSwitch = 0;
      for( int i=24; i>=0; i-=8)
      {
        optionSwitch |= ((uint32_t) ReadOne165()) << i;
      }

      for( int i = 0; i<32; i++)
      {
        if( bitRead( optionSwitch, i) != bitRead( oldOptionSwitch,i))
        {
          Serial.print( "Switch ");
          if( i < 10)
            Serial.print( " ");
          Serial.print( i);
          Serial.print( " is now ");
          Serial.println( bitRead( optionSwitch, i) == 0 ? "down ↓" : "up   ↑");
        }
      }

      oldOptionSwitch = optionSwitch;
      delay( 25);      // slow down the sketch to avoid switch bounce
    }

    // The ReadOne165() function reads only 8 bits,
    // because of the similar functions shiftIn() and SPI.transfer()
    // which both use 8 bits.
    //
    // The shiftIn() can not be used here, because the clock is set idle low
    // and the shiftIn() makes the clock high to read a bit.
    // The 74HC165 require to read the bit first and then give a clock pulse.
    //
    byte ReadOne165()
    {
      byte ret = 0x00;

      // The first one that is read is the highest bit (input D7 of the 74HC165).
      for( int i=7; i>=0; i--)
      {
        if( digitalRead( dataPin) == HIGH)
          bitSet( ret, i);

        digitalWrite( clockPin, HIGH);
        delayMicroseconds( pulseWidth);
        digitalWrite( clockPin, LOW);
      }

      return( ret);
    }

Link to the shift register project: https://wokwi.com/arduino/projects/306024460940476993

  [1]: https://i.stack.imgur.com/sC97W.png
  [2]: https://wokwi.com/arduino/projects/294980637632233994
  [3]: https://i.stack.imgur.com/hMwoh.gif

body:
Max buttons for min pins (via electrical engineering and busy wait in interupt)
-

Hook up each button to an interrupt **and** an analog pin. You can use **the same** interrupt and analog pins for all buttons, if you use resistors to discern between the buttons.

Use the interrupt pin to get notified, when a button is pushed. Use the resistors to have a different target voltage for each button in a voltage divider. Then in the interrupt handler use the analog pin to measure the voltage.
The main problem is that the voltage will take some time to stabilize after the interrupt already fired. I'd check for at least 3 consecutive identical readings (~30ms delay after the voltage stabilized).

Make sure you have some tolerance, e.g. by shifting at least the two least significant bits out (value = AnalogRead(PIN) >> TOLERANCE_BIT_COUNT;). With the analog pins' 10 bit resolution (1024 values, AFAIR), 2 bits lost for tolerance and an additional bit lost for difference between HI and LO (needed to trigger the interrupt), there are at least 7 bits left, which could suffice for up to 127 buttons.

Yes, you can hook up a keyboard with 2 pins, if you implement part of the logic in hardware (127 carefully designed voltage dividers) and part in software (detecting stabilized voltage). However the identification which button is pressed can be susceptible to deviations in voltage as small as 4.8 mV (a difference of 1 in the value of AnalogRead, which might carry over the tolerance). Also you can not detect multiple buttons being pushed at the same time. However if the electrical design has been carefully engineered, no failure detection may be needed for multiple buttons being pushed, because the interrupt would not fire, depending on how the target voltages stack up.

Electrical engineering problems to be solved:
- Designing the voltage dividers is left to the reader, because you can crank up the tolerance, if you need less buttons. This may mitigate the susceptibility to small deviations in voltage. My proposal would be to get X identical resistors of R Ohm for X buttons. Connect the resistors in series and fork the voltage between the resistors via the buttons. Connect all forks after their respective button to the analog pin and another resistor (of X times R Ohm) to either ground or Vcc (depending on the choice of interrupt HI vs. LO). Add a pull-up/down resistor to the end of the resistors in series as necessary.
- You might need to make sure not to lose too many bits too early, because otherwise there might be consecutive "identical" values without the voltage having stabilized.
- Check, if the interrupt should fire for HI->LO or LO->HI, as one might offer more distinct target voltages than the other. I just assumed that the first AnalogRead will return a value of about 512 either way.
- I remember that you can remap the values of AnalogRead to regain the 1 bit lost to HI-LO vs. LO-HI transition. This is not recommended as it might interfere with the behaviour of other analog pins. However in a pinch this may either double the number of buttons possible or add another bit for tolerance.
- A small capacitor might help to filter bumping out of the buttons' switching action, so you don't get multiple interrupts for a single button push. However this may increase the time needed for the voltage divider to stabilize at the target voltage. So choose the smallest capacitor and resistors, you can get away with.

body:
## A different take

Use an app to make on-screen virtual controls instead of using physical buttons, and send press events over bluetooth or wifi or ESPNOW.

### Advantages

* no parts needed if you have a phone/laptop already
* no soldering
* no flaky parts wearing out
* complete control over button layout
* easy to upgrade/modify control layout based on field experience
* one less part to carry
* trivial to have extra backup remotes
* opens the door to macros (eg. auto-land), test routines, etc
* lets you log data from the robot for debugging
* EASILY add cool control hardware like gamepads, voice, or camera
* much easier to code buttons in, eg. HTML+JS than C++
* separates programming concerns and allows detached evolution
* allows possibility of internet/remote control
* can be developed on laptop, moved to portable raspPi or phone
* can control more than one (or a new) robot from the remote control

### Disdvantages
* needs code in two languages
* extra part (eg. ESP8266), though buttons are expensive too
* slightly increased latency (but buttons should be debounced anyway)
* might not be as satisfying as a 80+ hour hand-built controller
* requires a bit of security consideration (maybe)

All in all, I think the advantages FAR outweigh the drawbacks. If you need soldering practice and human-held hardware design experience, a physical remote is a decent project, but you can always do that later once you get the robot working with abstract commands; you don't have to build and debug both at the same time, which is huge to me...

### If you NEED a physical remote
You can still get many of the above benefits in a physical remote if you put an MCU/SBC in the remote. Then talk to the robot with uart/wifi/bt/etc. Uart lets you run just 4 wires to the remote instead of dozens. There's lots of existing 4+wire connectors (USB-B, RJ-45, XLR, DIN, etc) that you can use for this; thin, light, cheap, replaceable. Such a config  allows serial debugging, logging, etc. It frees the robot CPU from having to deal with interrupts and library footprints.

All in all, it will make making faster for the small cost of a cheap MCU like a nano/bluepill/esp32...


body:
Good evening guys,

Looking for any help on interfacing the above GSM/GPRS module with arduino.

Connections:

VCC and GND of module- separate power supply, 5v 3A

URX to pin 2
UTX to pin 3

Common GND between arduino and separate supply.

Tried AT command code for A6 module, getting +CREG:3 on serial monitor.

Same connections as above with GSM send messages code example on arduino-

Doesn't go past "Sms messages sender

title: Interfacing IOT- GA6 to Arduino

Answers: 0


body:
I am trying to write to the adafruit display using Arduino MKR1500 when it is connected to the internet. The issue I am facing is when I add the code to connect to the cloud, the display stops working. If I removed that piece of code, the display outputs correctly.
As of now I am just printing "hello world" on the screen.
Below is the code without the cloud connection:
````
/**************************************************************************
  This is a library for several Adafruit displays based on ST77* drivers.

  Works with the Adafruit 1.8" TFT Breakout w/SD card
    ----> http://www.adafruit.com/products/358
  The 1.8" TFT shield
    ----> https://www.adafruit.com/product/802
  The 1.44" TFT breakout
    ----> https://www.adafruit.com/product/2088
  The 1.14" TFT breakout
  ----> https://www.adafruit.com/product/4383
  The 1.3" TFT breakout
  ----> https://www.adafruit.com/product/4313
  The 1.54" TFT breakout
    ----> https://www.adafruit.com/product/3787
  The 2.0" TFT breakout
    ----> https://www.adafruit.com/product/4311
  as well as Adafruit raw 1.8" TFT display
    ----> http://www.adafruit.com/products/618

  Check out the links above for our tutorials and wiring diagrams.
  These displays use SPI to communicate, 4 or 5 pins are required to
  interface (RST is optional).

  Adafruit invests time and resources providing this open source code,
  please support Adafruit and open-source hardware by purchasing
  products from Adafruit!

  Written by Limor Fried/Ladyada for Adafruit Industries.
  MIT license, all text above must be included in any redistribution
 **************************************************************************/
#include <Adafruit_Fingerprint.h>
#include <Adafruit_GFX.h>    // Core graphics library
#include <Adafruit_ST7735.h> // Hardware-specific library for ST7735
#include <Adafruit_ST7789.h> // Hardware-specific library for ST7789
#include <SPI.h>
#include <Bounce2.h> // https://github.com/thomasfredericks/Bounce2
//#include <EEPROM.h>
#include <FlashStorage.h>

#if defined(ARDUINO_FEATHER_ESP32) // Feather Huzzah32
#define TFT_CS         14
#define TFT_RST        15
#define TFT_DC         32

#elif defined(ESP8266)
#define TFT_CS         4
#define TFT_RST        16
#define TFT_DC         5

#else
// For the breakout board, you can use any 2 or 3 pins.
// These pins will also work for the 1.8" TFT shield.
#define TFT_CS        1 // D v25 changes to use pin 1 for CS in MKR1500
#define TFT_RST        -1 // Or set to -1 and connect to Arduino RESET pin // D v25 changes to use built in reset pinout in MKR1500
#define TFT_DC         2 // D v25 changes to use pin 2 for CS in MKR1500
#endif

//D v15 for audrino to connect to fingerprint sensor
//D v2
#if (defined(__AVR__) || defined(ESP8266)) && !defined(__AVR_ATmega2560__)
// For UNO and others without hardware serial, we must use software serial...
// pin #2 is IN from sensor (GREEN wire)
// pin #3 is OUT from arduino  (WHITE wire)
// Set up the serial port to use softwareserial..
SoftwareSerial mySerial(2, 4);

#else
// On Leonardo/M0/etc, others with hardware serial, use hardware serial!
// #0 is green wire, #1 is white
#define mySerial Serial1

#endif

// OPTION 1 (recommended) is to use the HARDWARE SPI pins, which are unique
// to each board and not reassignable. For Arduino Uno: MOSI = pin 11 and
// SCLK = pin 13. This is the fastest mode of operation and is required if
// using the breakout board's microSD card.

// For 1.44" and 1.8" TFT with ST7735 use:
//Adafruit_ST7735 tft = Adafruit_ST7735(TFT_CS, TFT_DC, TFT_RST); // D v21 uncomment this and comment the line below to use 1.44inch display.Need to change the display font in case I use 1.44"

// For 1.14", 1.3", 1.54", and 2.0" TFT with ST7789:
Adafruit_ST7789 tft = Adafruit_ST7789(TFT_CS, TFT_DC, TFT_RST); // D v22 uncommment to use this display

#include <ArduinoHttpClient.h>
#include <ArduinoJson.h>
#include <MKRNB.h>

// Debug options
#define PRINT_AT        true   // Show or hide AT command output from the modem

// PIN Number
const char PINNUMBER[]     = "";
char apn[] = "soracom.io";
char user[] = "sora";
char pass[] = "sora";

// Server details
const char server[] = "unified.soracom.io";
const int  port = 80;

NBClient client;
GPRS gprs;
NB nbAccess(PRINT_AT);
HttpClient http(client, server, port);

// connection state
  bool connected = false;

// Publish interval
long previousMillis = 0;
long interval = 1000; // milliseconds // D v2orginial value: long interval = 20000; chnages the time interval in which it will report

void setup(void) {

  // tft.initR(INITR_144GREENTAB); // Init ST7735R chip, green tab

  // OR use this initializer (uncomment) if using a 1.3" or 1.54" 240x240 TFT:
  tft.init(240, 240);           // Init ST7789 240x240  // D v22 uncommment to use this display

  // tft print function!
  tftPrintTest();

  pinMode(SARA_RESETN, OUTPUT);
  digitalWrite(SARA_RESETN, LOW);
  pinMode(SARA_PWR_ON, OUTPUT);

  //Initialize serial and wait for port to open:
  Serial.begin(115200);

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

  start_and_connect_modem();

  }

 void loop() {
  tft.invertDisplay(true);
  delay(500);

  tft.setTextColor(ST77XX_GREEN);
  tft.setCursor(0, 10);

    tft.setCursor(0, 0);
    tft.fillScreen(ST77XX_BLACK);

    tft.println("hello world");

    }

void tftPrintTest() {
  tft.setRotation(3);
  tft.setTextWrap(true);
  tft.fillScreen(ST77XX_BLACK);
  tft.setCursor(0, 0);
  tft.setTextColor(ST77XX_GREEN);
  tft.setTextSize(2);
}

````

Below is the code with the cloud connection added
````
/**************************************************************************
  This is a library for several Adafruit displays based on ST77* drivers.

  Works with the Adafruit 1.8" TFT Breakout w/SD card
    ----> http://www.adafruit.com/products/358
  The 1.8" TFT shield
    ----> https://www.adafruit.com/product/802
  The 1.44" TFT breakout
    ----> https://www.adafruit.com/product/2088
  The 1.14" TFT breakout
  ----> https://www.adafruit.com/product/4383
  The 1.3" TFT breakout
  ----> https://www.adafruit.com/product/4313
  The 1.54" TFT breakout
    ----> https://www.adafruit.com/product/3787
  The 2.0" TFT breakout
    ----> https://www.adafruit.com/product/4311
  as well as Adafruit raw 1.8" TFT display
    ----> http://www.adafruit.com/products/618

  Check out the links above for our tutorials and wiring diagrams.
  These displays use SPI to communicate, 4 or 5 pins are required to
  interface (RST is optional).

  Adafruit invests time and resources providing this open source code,
  please support Adafruit and open-source hardware by purchasing
  products from Adafruit!

  Written by Limor Fried/Ladyada for Adafruit Industries.
  MIT license, all text above must be included in any redistribution
 **************************************************************************/
#include <Adafruit_Fingerprint.h>
#include <Adafruit_GFX.h>    // Core graphics library
#include <Adafruit_ST7735.h> // Hardware-specific library for ST7735
#include <Adafruit_ST7789.h> // Hardware-specific library for ST7789
#include <SPI.h>
#include <Bounce2.h> // https://github.com/thomasfredericks/Bounce2
//#include <EEPROM.h>
#include <FlashStorage.h>

#if defined(ARDUINO_FEATHER_ESP32) // Feather Huzzah32
#define TFT_CS         14
#define TFT_RST        15
#define TFT_DC         32

#elif defined(ESP8266)
#define TFT_CS         4
#define TFT_RST        16
#define TFT_DC         5

#else
// For the breakout board, you can use any 2 or 3 pins.
// These pins will also work for the 1.8" TFT shield.
#define TFT_CS        1 // D v25 changes to use pin 1 for CS in MKR1500
#define TFT_RST        -1 // Or set to -1 and connect to Arduino RESET pin // D v25 changes to use built in reset pinout in MKR1500
#define TFT_DC         2 // D v25 changes to use pin 2 for CS in MKR1500
#endif

//D v15 for audrino to connect to fingerprint sensor
//D v2
#if (defined(__AVR__) || defined(ESP8266)) && !defined(__AVR_ATmega2560__)
// For UNO and others without hardware serial, we must use software serial...
// pin #2 is IN from sensor (GREEN wire)
// pin #3 is OUT from arduino  (WHITE wire)
// Set up the serial port to use softwareserial..
SoftwareSerial mySerial(2, 4);

#else
// On Leonardo/M0/etc, others with hardware serial, use hardware serial!
// #0 is green wire, #1 is white
#define mySerial Serial1

#endif

// OPTION 1 (recommended) is to use the HARDWARE SPI pins, which are unique
// to each board and not reassignable. For Arduino Uno: MOSI = pin 11 and
// SCLK = pin 13. This is the fastest mode of operation and is required if
// using the breakout board's microSD card.

// For 1.44" and 1.8" TFT with ST7735 use:
//Adafruit_ST7735 tft = Adafruit_ST7735(TFT_CS, TFT_DC, TFT_RST); // D v21 uncomment this and comment the line below to use 1.44inch display.Need to change the display font in case I use 1.44"

// For 1.14", 1.3", 1.54", and 2.0" TFT with ST7789:
Adafruit_ST7789 tft = Adafruit_ST7789(TFT_CS, TFT_DC, TFT_RST); // D v22 uncommment to use this display

#include <ArduinoHttpClient.h>
#include <ArduinoJson.h>
#include <MKRNB.h>

// Debug options
#define PRINT_AT        true   // Show or hide AT command output from the modem

// PIN Number
const char PINNUMBER[]     = "";
char apn[] = "soracom.io";
char user[] = "sora";
char pass[] = "sora";

// Server details
const char server[] = "unified.soracom.io";
const int  port = 80;

NBClient client;
GPRS gprs;
NB nbAccess(PRINT_AT);
HttpClient http(client, server, port);

// connection state
  bool connected = false;

// Publish interval
long previousMillis = 0;
long interval = 1000; // milliseconds // D v2orginial value: long interval = 20000; chnages the time interval in which it will report

void setup(void) {

  // tft.initR(INITR_144GREENTAB); // Init ST7735R chip, green tab

  // OR use this initializer (uncomment) if using a 1.3" or 1.54" 240x240 TFT:
  tft.init(240, 240);           // Init ST7789 240x240  // D v22 uncommment to use this display

  // tft print function!
  tftPrintTest();

  pinMode(SARA_RESETN, OUTPUT);
  digitalWrite(SARA_RESETN, LOW);
  pinMode(SARA_PWR_ON, OUTPUT);

  //Initialize serial and wait for port to open:
  Serial.begin(115200);

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

  start_and_connect_modem();

  }

 void loop() {
  tft.invertDisplay(true);
  delay(500);

  tft.setTextColor(ST77XX_GREEN);
  tft.setCursor(0, 10);

    tft.setCursor(0, 0);
    tft.fillScreen(ST77XX_BLACK);

    tft.println("hello world");

    }

void tftPrintTest() {
  tft.setRotation(3);
  tft.setTextWrap(true);
  tft.fillScreen(ST77XX_BLACK);
  tft.setCursor(0, 0);
  tft.setTextColor(ST77XX_GREEN);
  tft.setTextSize(2);
}

void post_data(String postData) {
 //Serial.println("making POST request");
  String contentType = "application/json";

  http.post("/", contentType, postData);

  // read the status code and body of the response
  int statusCode = http.responseStatusCode();
  String response = http.responseBody();

  /*Serial.print("Status code: ");
  Serial.println(statusCode);
  Serial.print("Response: ");
  Serial.println(response);*/

}

void start_and_connect_modem(){
  pinMode(SARA_RESETN, OUTPUT);
  digitalWrite(SARA_RESETN, LOW);
  pinMode(SARA_PWR_ON, OUTPUT);

  // Send Poweron pulse
  digitalWrite(SARA_PWR_ON, HIGH);
  delay(150);
  digitalWrite(SARA_PWR_ON, LOW);
  delay(500);
  // Turn on the modem
  if (Serial) Serial.print(">>> Turning on modem...");
  if (MODEM.begin()) {
    if (Serial) Serial.println(" done!");
  } else {
    if (Serial) Serial.println(" error, could not turn on modem! Try power-cycling.");
    return;
  }

  while (!MODEM.noop());
  MODEM.sendf("ATI9");
  MODEM.waitForResponse(2000);

  // Run AT commands to reset the modem to global default settings
  Serial.print(">>> Resetting modem to default settings...");
  MODEM.sendf("AT+CFUN=0");
  MODEM.waitForResponse(6000);
  MODEM.sendf("AT+UMNOPROF=2");
  MODEM.waitForResponse(2000);
  MODEM.sendf("AT+CFUN=15");
  MODEM.waitForResponse(6000);
  MODEM.sendf("AT+CFUN=0");
  MODEM.waitForResponse(2000);
  MODEM.sendf("AT+UMNOPROF=0");
  MODEM.waitForResponse(2000);
  MODEM.sendf("AT+CFUN=15");
  MODEM.waitForResponse(2000);
  MODEM.sendf("AT+URAT=7");
  MODEM.waitForResponse(2000);
  //D v33
  /*MODEM.sendf("AT+UBANDMASK?");
  MODEM.waitForResponse(6000);*/
  Serial.println(" done!");

  delay(2000);
  // attempt to connect to GSM and GPRS:
  Serial.print("Attempting to connect to GSM and GPRS");
  //Serial.println();
  connect_modem();

}

void connect_modem(){
  // After starting the modem with GSM.begin()
  // attach the shield to the GPRS network with the APN, login and password
  while (!connected) {
    if ((nbAccess.begin(PINNUMBER, apn, user, pass) == NB_READY) &&
        (gprs.attachGPRS() == GPRS_READY)) {
      connected = true;
    } else {
      Serial.println("Not connected");
      delay(1000);
    }
  }

  Serial.println("You're connected to the network");
}
````

Can someone please let me know what I am missing?

title: Issue displaying on Adafruit display when enabling GSM communication

Answers: 0


body:
32-bit ARM-Based microcontroller SAM D21E / SAM D21G /SAM D21J

I have a Seeeduino XIAO [PDF to schematic][1] which uses a [ATSAMD21G18-QFN48][2] chip. Pin D1 on the Seeeduino is pin 9 on the chip; which is labeled as `PA4/EIC/REF/AIN4/SCOM0PAD0/TC0`.

[![screenshot with highlighted pin in question][4]][4]

What would the `REF` pin be used for; and how would the pin be addressed in the code?

Based on [this post][3] is sound like it is ADC related.

There is no indication about this on the https://wiki.seeedstudio.com/Seeeduino-XIAO/ website. Only this image:
 [![Seeeduino XIAO pin layout][5]][5]

  [1]: https://files.seeedstudio.com/wiki/Seeeduino-XIAO/res/Seeeduino-XIAO-v1.0-SCH-191112.pdf
  [2]: http://ww1.microchip.com/downloads/en/devicedoc/40001884a.pdf
  [3]: https://arduino.stackexchange.com/a/24529/71398
  [4]: https://i.stack.imgur.com/iBtpy.gif
  [5]: https://i.stack.imgur.com/yeuXO.jpg

title: What is the REF pin for -- pin 9 on ATSAMD21G18-QFN48?

Answers: 1

body:
PA04 pin can be a normal GPIO or a voltage reference pin (similar to VDDANA). So, the ADC input will be compared to this VREF pin in the application if needed. If you have configured it as GPIO, then it will behave as a normal IO pin. It depends on how you configure it.
[![enter image description here][1]][1]
[![enter image description here][2]][2]
[![enter image description here][3]][3]

  [1]: https://i.stack.imgur.com/RyOkB.png
  [2]: https://i.stack.imgur.com/wuIvg.png
  [3]: https://i.stack.imgur.com/BKDiO.png


body:
I need a way to prevent someone from cloning code from arduino. Without protection it can be cloned with advdudees in 2 min. I'm using atmega328p chip on nano. In this state arduino acts as a handshake for windows program i need to protect. There is nothing special or of value on arduino, but the custom handshake. One arduino for one .exe file. All arduino code is uploaded from arduino ide.

I did research and here it is.
1. Lock fuse bits. As i understood once locked flash and eeprom cant be read. When they are unlocked flash and eeprom are erased. I need one more arduino to act as programator.
2. Use some other unique hard to copy module like rfid card or bluetooth/wifi mac address. This is bad because it takes too much pins on nano.
3. Subtly solder 2 digital pins and set one to output and other to input. If not connected break loop.
4. Usb hardware dongle licence. I have no idea how to create one and it seems like some relic of the past. Custom file system or something...

I'd like to keep arduino nano for deployment.

There is no internet involved. If program had access to internet i'd just use db.

Thanks in advance.

title: Prevent flash cloning

Answers: 1

body:
Using the lock fuse bits is definitely the correct step here. Unlocking is not a problem, since the memory will be erased in that step and you cannot prevent reflashing anyway.

---

Very important note from Gerben in the comments:

> Note that setting the lock bits is pointless, while the Arduino bootloader is installed. The bootloader can still read out the program, even with the lock bits set. You'd have to remove the bootloader and upload the code using the ISP interface (ArduinoAsISP).

The lock bits only work for the ISP interface, which can be used to program the Arduino. The bootloader (which is part of the program on  the Arduino) still can read the program memory (it has to, since it is executed from there). Thus to prevent someone from reading out the program through the bootloader, you need to remove the bootloader. Programming is then done just like you are setting the fuses: Through ISP (for example via a second Arduino).

---

You didn't include details on the handshake. An important attack route would be to just sniff on the Arduinos Serial interface. Unless your handshake itself is encrypted locking the Arduino will not prevent attackers from getting it.

There are encryption libraries for Arduino (like [this one on github][1]). Based on your thread model and the needed resources (since the Uno is rather constrained especially in RAM) you can choose a fitting library and a fitting encryption algorithm. One important attack route would be a replay attack, where the attacker just resends the serial data, that he recorded in the last successfull transmission. One way to prevent that would be a rolling code (like modern garage door openers often use). Or you can create One-Time-Passwords (for example by combining the handshake secret with a timestamp and encrypting/hashing that; you need synchronized time for that).

  [1]: https://rweather.github.io/arduinolibs/crypto.html


body:
I am looking to use an Arduino in a motor control application, and have found that the VESC^ project has done some good work in this. I would like to have some fine-grain control over the motor drive, but using the VESC foundation looks great.

Research so far on Arduino and VESC discusses using an Arduino to interface with VESC hardware, however I'd be more interested in having the VESC firmware running *on* the Arduino, with output driving a power stage.

Is there a reason why this is not possible? (where the most powerful Arduino being insufficient on processing, not enough memory, etc.)

^VESC is an open Electronic Speed Control infrastructure for motor control that in completeness includes hardware, firmware and parameterisation/control sotfware. [VESC Project website.][1]

  [1]: https://vesc-project.com

title: Is there a VESC firmware implementation that runs on Arduino?

Answers: 0


body:
I am trying to write to a specific register, but value doesn't change.

Working with SenseAir Sunrise CO2:
Info from i2c guideline from sensor manufacter
https://rmtplusstoragesenseair.blob.core.windows.net/docs/Dev/publicerat/TDE5531.pdf

> Measurement Period (EE) 0x96 (MSB) 0x97 (LSB)
>
> Measurement period in seconds (range from 2 to 65534). Odd numbers
> will be rounded up to nearest even number. A system reset is required
> after changing configuration. Default value is 16.

And that's my code snippet

```
#include <Wire.h>

/* WARINING!!!
  Some wire driver implementations do not corectly implement Wire.endTransmission(false) function,
  so please check this before disable WIRE_WORKAROUND!
  For example, known "bad" implementations are: Nucleo STM32
 */
#define WIRE_WORKAROUND   (0)

#define LED_BUILTIN 2

/* Define serial EN pin */
const int       SUNRISE_EN              = 4;

/* Sunrise communication address, both for Modbus and I2C */
const uint8_t   SUNRISE_ADDR            = 0x68;

/* Amount of wakeup attempts before time-out */
const int       ATTEMPTS                 = 5;
/* It takes 25ms to write one EE register */
const int       EEPROM_UPDATE_DELAY_MS   = 25;

/* Register Addresses */
const uint8_t ERROR_STATUS             = 0x01;
const uint8_t MEASUREMENT_MODE         = 0x95;
const uint8_t METER_CONTROL            = 0xA5;

/* Reading period, in milliseconds. Default is 4 seconds */
int readPeriodMs = 2000;

void setup()
{
  /* I2C */
  /* Initialize I2C and use default pins defined for the board */
  reInitI2C();

  Serial.begin(115200);

  Serial.println("Initialization complete\n");

  change_measurement_period(SUNRISE_ADDR);

  /* Read the sensor's configs */
  Serial.println("Sensor Measurement Configurations:");
  read_sensor_config(SUNRISE_ADDR);
  Serial.println();
}

void change_measurement_period(uint8_t target) {
  /* Function variables */
  int error;

  /* Wakeup */
  if(!(_wakeup(target))) {
    Serial.print("Failed to wake up sensor.");
    /* FATAL ERROR */
    while(true);
  }

  Serial.println("Changing Measurement Period...");

  uint16_t mPeriod = 12;

  Wire.beginTransmission(target);
  Wire.write(0x96);
  Wire.write(highByte(mPeriod));      // sends MSB
  Wire.write(lowByte(mPeriod));       // sends LSB
  error = Wire.endTransmission(true);
  delay(EEPROM_UPDATE_DELAY_MS);

  if(error != 0) {
    Serial.print("Failed to send request. Error code: ");
    Serial.println(error);
    /* FATAL ERROR */
    while(true);
  }

  Serial.println("\n\n\nSensor restart is required to apply changes\n\n\n");
}

/**
 * @brief  Reads and prints the sensor's current measurement mode,
 *         measurement period and number of samples.
 *
 * @param  target: The sensor's communication address
 * @note   This example shows a simple way to read the sensor's
 *         measurement configurations.
 * @retval None
 */
void read_sensor_config(uint8_t target) {
  /* Function variables */
  int error;
  int numBytes = 7;

  /* Wakeup */
  if(!(_wakeup(target))) {
    Serial.print("Failed to wake up sensor.");
    return;
  }

  /* Request values */
  error = WireRequestFrom(target, numBytes, MEASUREMENT_MODE /* from address*/, true /* STOP*/);
  if(error != numBytes ) {
    Serial.print("Failed to write to target. Error code : ");
    Serial.println(error);
    return;
  }

  /* Read values */
  /* Measurement mode */
  uint8_t measMode = Wire.read();

  /* Measurement period */
  uint8_t byteHi = Wire.read();
  uint8_t byteLo = Wire.read();
  uint16_t measPeriod = ((int16_t)(int8_t) byteHi << 8) | (uint16_t)byteLo;

  /* Number of samples */
  byteHi = Wire.read();
  byteLo = Wire.read();
  uint16_t numSamples = ((int16_t)(int8_t) byteHi << 8) | (uint16_t)byteLo;

  /* ABCPeriod */
  byteHi = Wire.read();
  byteLo = Wire.read();
  uint16_t abcPeriod = ((int16_t)(int8_t) byteHi << 8) | (uint16_t)byteLo;

  /* Most propable that the sensor will not go into sleep mode, but to be insure...*/
  /* Wakeup */
  if(!(_wakeup(target))) {
    Serial.print("Failed to wake up sensor.");
    return;
  }

  /* Request values */
  error = WireRequestFrom(target, 1, METER_CONTROL /* from address*/, true /* STOP*/);
  if(error != 1 ) {
    Serial.print("Failed to write to target. Error code : ");
    Serial.println(error);
    return;
  }

  uint8_t meterControl = Wire.read();

  Serial.print("Measurement Mode: ");
  Serial.println(measMode);

  readPeriodMs = measPeriod * 1000;

  Serial.print("Measurement Period, sec: ");
  Serial.println(measPeriod);

  Serial.print("Number of Samples: ");
  Serial.println(numSamples);

  if((0U == abcPeriod) ||  (0xFFFFU == abcPeriod) || (meterControl & 0x02U)) {
    Serial.println("ABCPeriod: disabled");
  } else {
    Serial.print("ABCPeriod, hours: ");
    Serial.println(abcPeriod);
  }

  Serial.println("MeterControl: ");
  Serial.println("Bit [0]:" + (String)bitRead(meterControl,0));
  Serial.println("Bit [1]:" + (String)bitRead(meterControl,1));
  Serial.println("Bit [2]:" + (String)bitRead(meterControl,2));
  Serial.println("Bit [3]:" + (String)bitRead(meterControl,3));
  Serial.println("Bit [4]:" + (String)bitRead(meterControl,4));
  Serial.println("Bit [5]:" + (String)bitRead(meterControl,5));
  Serial.println("Bit [6]:" + (String)bitRead(meterControl,6));
  Serial.println("Bit [7]:" + (String)bitRead(meterControl,7));
  Serial.println(meterControl, BIN);

}

/* Initialize I2C bus and pins */
void  reInitI2C() {
  /* Initialize I2C and use default pins defined for the board */
  Wire.begin();
  /* Setup I2C clock to 100kHz */
  Wire.setClock(100000);
}

/* Workaround regarding BAD implementations of Wire.endTransmission(false) function */
int WireRequestFrom(uint8_t dev_addr, uint8_t bytes_numbers, uint8_t offset_to_read, bool stop) {
 int error;
#if (WIRE_WORKAROUND == 1)
 error = Wire.requestFrom((uint8_t)dev_addr, (uint8_t)bytes_numbers /* how many bytes */, (uint32_t)offset_to_read /* from address*/, (uint8_t)1/* Address size - 1 byte*/, stop /* STOP*/);
#else
  Wire.beginTransmission(dev_addr);
  Wire.write(offset_to_read); //starting register address, from which read data
  Wire.endTransmission(false);
  error = Wire.requestFrom((uint8_t)dev_addr, (uint8_t)bytes_numbers /* how many bytes */, (uint8_t)stop /* STOP*/);
#endif
  return error;
}

/**
 * @brief  Wakes up the sensor by initializing a write operation
 *         with no data.
 *
 * @param  target:      The sensor's communication address
 * @note   This example shows a simple way to wake up the sensor.
 * @retval true if successful, false if failed
 */
bool _wakeup(uint8_t target)
{
  int attemps = ATTEMPTS;
  int error;

  do {
    uint8_t byte_0;
    /* */
    Wire.beginTransmission(target);
    error = Wire.endTransmission(true);
  } while(((error != 0 /*success */) && (error != 2 /*Received NACK on transmit of address*/) && (error != 1 /* BUG in STM32 library*/)) && (--attemps > 0));
  /* STM32 driver can stack under some conditions */
  if(error == 4) {
    /* Reinitialize I2C*/
    reInitI2C();
    return false;
  }
  return (attemps > 0);
}

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

}

```

Mostly i use that code, but it's not have an snippet with writing random number in register with MSB&LSB:
https://github.com/Senseair-AB/Sunrise-Examples---Arduino/blob/master/examples/i2c/sunrise_i2c_continuous/sunrise_i2c_continuous.ino

i reset sensor hardware(physically push the reset button and toogle power from sensor) after data was written and also i wait until all bytes are written
`delay(EEPROM_UPDATE_DELAY_MS);`
Also i read the sensor configuration after startup, and i see that values of registers doesn't change.

Problem in function **change_measurement_period**

What am i doing wrong? maybe someone can help with that?

title: Writing to a specific I2C register

Answers: 2

body:
As written on page 14 of the linked document (emphasis by me):

> All new written data to register (EE) can be read back **after a sensor reset is completed**.

But it seems as if you don't reset the sensor.

You will need to wait as documented, until all bytes are written.

body:
My main goal was to use the opportunity to get the value compensated by atmospheric pressure.
But for this it was necessary to understand how to write in registers.

And did not understand what was the problem in the examples of code provided by the manufacturer, it did not correctly work with writing to register 2 bytes data or і did something wrong (most likely).
So I rewrote it with the help of a man from the Arduino forum, and now everything works fine.

```
    //Write pressure value to register BAROMETRIC_PRESSURE_VALUE
    int16_t co2Pre = 9772; //977.2 hPa

    // The wake-up is a write command to the I2C address of the sensor.
    Wire.beginTransmission(SUNRISE_ADDR);
    Wire.endTransmission();                   // ignore the return value

    Wire.beginTransmission(SUNRISE_ADDR);
    Wire.write(BAROMETRIC_PRESSURE_VALUE);
    Wire.write(highByte(co2Pre));      // sends MSB
    Wire.write(lowByte(co2Pre));       // sends LSB
    error = Wire.endTransmission(true);
    delay(50);

    if( error != 0) Serial.println( "ERROR, can't find the sensor");
```

```
  int WireRequest(byte target, byte regAddr, int numBytes) {
  // The wake-up is a write command to the I2C address of the sensor.
  Wire.beginTransmission(target);
  Wire.endTransmission();                   // ignore the return value

  // Set register address of the sensor
  Wire.beginTransmission(target);
  Wire.write(regAddr);                        // register address
  int error = Wire.endTransmission(false); // false for a repeated start

  if( error != 0) {
    Serial.println( "ERROR, can't find the sensor");
    return 1;
  }

  // Read the temperature (two bytes, representing a signed integer)
  int n = Wire.requestFrom(target, numBytes);       // request 2 bytes

  if( n != numBytes) {
    Serial.println( "ERROR, can't read data");
    return 1;
  }

  return 0;
}

    //read BAROMETRIC_PRESSURE_VALUE
    error = WireRequest(SUNRISE_ADDR, BAROMETRIC_PRESSURE_VALUE, 2);
    if(error != 0) {
      Serial.println( "Failed to write to target.");
      while(true);
    }
    msb = (byte) Wire.read();
    lsb = (byte) Wire.read();
    int16_t co2Pressure = word( msb, lsb);
    float co2PressureValue = float( co2Pressure) / 10;
    Serial.println("BAROMETRIC_PRESSURE_VALUE: " + (String) co2PressureValue);
```

And also working code snippets for writing registers, that need sensor restart, later i physically restart the sensor, but now do it in code.

```
    // The wake-up is a write command to the I2C address of the sensor.
    Wire.beginTransmission(SUNRISE_ADDR);
    Wire.endTransmission();                   // ignore the return value

    Wire.beginTransmission(SUNRISE_ADDR);
    Wire.write(MEASUREMENT_PERIOD);
    Wire.write(highByte(mPeriod));      // sends MSB
    Wire.write(lowByte(mPeriod));       // sends LSB
    error = Wire.endTransmission(true);
    delay(50);

    if( error != 0) Serial.println( "ERROR, can't find the sensor");

    //RESTART SENSOR
    // The wake-up is a write command to the I2C address of the sensor.
    Wire.beginTransmission(SUNRISE_ADDR);
    Wire.endTransmission();                   // ignore the return value

    Wire.beginTransmission(SUNRISE_ADDR);
    Wire.write(SENSOR_RESTART_SCR);
    Wire.write(0xFF);
    error = Wire.endTransmission(true);
    if( error != 0) Serial.println( "ERROR, can't find the sensor");

    Serial.println("\n\nSensor restart to apply changes\n\n");

    delay(2500); //Wait after sensor restart
```