body:
I am trying to understand how the clock speed in the esp32 works.

I am running arduino ide 1.8.12 with 1.04 board definition - on a pico kit 4 module .

The device datasheet says it has a 40mhz crystal.

getCpuFrequencyMhz() reports 240mhz

But the following code is generating 1sec interrupts with 80mhz as a base i.e., as if the clock speed is 80mhz.

If I explicitly set the clock speed to 80 mhz then getCpufrequency correctly reports it as 80, and the code still keeps generating 1sec interrupts (as it should at 80). If I set the clock to 40mhz then I finally see interrupts at 2 secs as would be expected. What is the deal with the 240 report for what is actually 80 and where is 80 coming from on a supposedly 40 mhz part?

I am sure that the explanation is somewhere in expressif's docs, but I have been unable to glean it. Can anyone quickly explain what is going on or point me to some resource that explains this particular circumstance?

    ---------------
    Sample output
    getCpuFrequencyMhz() = 240
    interrupts so far = 1 - : - mills() = 1018
    interrupts so far = 2 - : - mills() = 2018
    interrupts so far = 3 - : - mills() = 3018
    interrupts so far = 4 - : - mills() = 4018
    interrupts so far = 5 - : - mills() = 5018

----------------Sample code

    #include "esp32-hal-cpu.h"

    volatile int interruptCounter;
    int totalInterruptCounter;

    hw_timer_t * timer = NULL;
    portMUX_TYPE timerMux = portMUX_INITIALIZER_UNLOCKED;

    void IRAM_ATTR onTimer() {
      portENTER_CRITICAL_ISR(&timerMux);
      interruptCounter++;
      portEXIT_CRITICAL_ISR(&timerMux);

    }

    void setup() {

      Serial.begin(115200);

      Serial.printf("getCpuFrequencyMhz() = %d\n",getCpuFrequencyMhz()); //Get CPU clock

      timer = timerBegin(0, 80, true);
      timerAttachInterrupt(timer, &onTimer, true);
      timerAlarmWrite(timer, 1000000, true);
      timerAlarmEnable(timer);

    }

    void loop() {

      if (interruptCounter > 0) {

        portENTER_CRITICAL(&timerMux);
        interruptCounter--;
        portEXIT_CRITICAL(&timerMux);

        totalInterruptCounter++;

        Serial.printf("interrupts so far = %d - : - mills() = %d \n", totalInterruptCounter, millis());

      }
    }

title: esp32 pico kit - actual clock speed vs crystal vs max_speed etc

Answers: 0


body:
I am pairing an Arduino UNO with a Yost Labs 3-Space Sensor Nano, the user manual for said sensor can be found here: [1].

This is my code, pretty straight forward (although this is my first time working with SPI). I am 100% sure the wiring is correct.

I believe that as per the user manual, this should successfully return 3 floats in 4 bytes each, corresponding to the filtered euler angles of pitch, yaw, and roll. However, all I am reading is bytes full of 0xFF which I believe corresponds to null / no command.

Are there any visible errors in my code?

    #include <SPI.h>

    SPISettings settings(6000000, MSBFIRST, SPI_MODE0 ); //variable to hold SPI settings
    //Set Slave Select, MOSI, MISO, CLK
    const int CSN = 10;
    const int SI = 11;
    const int SO = 12;
    const int CLK = 13;

    // Needed to convert the bytes from SPI to float
    union u_types {
       byte b[4];
       float fval;
    } data[3];  // Create 3 unions, one for each euler angle

    void setup() {
     //Set Pin Modes
     pinMode(CSN, OUTPUT);
     pinMode(SI, OUTPUT);
     pinMode(SO, INPUT);
     pinMode(CLK, OUTPUT);
     //Set Slave Select High to Start i.e disable chip
     digitalWrite(CSN, HIGH);
     //Initialize SPI
     SPI.begin();
     //pour a bowl of serial
     Serial.begin(9600);
    }

    //function to transfer commands through SPI
    byte transferByte(byte byteToWrite) {

     byte Result = 0x00;
     digitalWrite(CSN,LOW);
     delay(1);
     Result = SPI.transfer(byteToWrite);
     delay(1);
     digitalWrite(CSN,HIGH);
     return Result;
    }

    //function to swap endian
    void endianSwap(byte temp[4]) {
     byte myTemp = temp[0];
     temp[0] = temp[3];
     temp[3] = myTemp;
     myTemp = temp[1];
     temp[1] = temp[2];
     temp[2] = myTemp;
    }

    void loop() {
     SPI.beginTransaction(settings);

     // Clear the internal data buffer on the IMU
     byte result = transferByte(0x01);
         Serial.print("Cleared internal buffer. Result: "),Serial.println(result);

     // Send start of packet:
     result = transferByte(0xF6);
          Serial.print("Send start of packet. Result: "),Serial.println(result);

     // Send command (tared euler angles)
     result = transferByte(0x01);
          Serial.print("Send commmand 0x01. Result: "),Serial.println(result);

     // Get status of device:
     result = transferByte(0xFF);
          Serial.print("Status of device. Result: "),Serial.println(result);

     while (result != 0x01) {  // Repeat until device is Ready
       delay(1);
       result = transferByte(0xFF);
       Serial.print("Status of device. Result: "),Serial.println(result);
     }

     // Get the 12 bytes of return data from the device:
     for (int ii=0; ii<3; ii++) {
       for (int jj=0; jj<4; jj++) {
         data[ii].b[jj] =  transferByte(0xFF);
         delay(1);
       }
     }

     SPI.endTransaction();

     for( int mm=0; mm<3; mm++) {
       endianSwap(data[mm].b);
     }

     Serial.print("fval 1:"), Serial.println(data[0].fval);
     Serial.print("fval 2:"), Serial.println(data[1].fval);
     Serial.print("fval 3:"), Serial.println(data[2].fval);

     delay(3000);
    }

  [1]: https://yostlabs.com/wp/wp-content/uploads/pdf/3-Space-Sensor-Users-Manual-Nano.pdf

title: SPI communications with an IMU

Answers: 0


body:
I've cobbled some code together from reading multiple sources on the web.  Makeatronics in particular to help me get this rotary encoder code together (shout out to them).  I'm pretty close to the end, but now trying to port it over the OLED display.  Not sure what the issue is, but it doesn't miss counter steps when read on the serial monitor, but does when ported to the OLED.

I increased the clock speed to 400Khz using Wire.setClock as I saw that suggested in some other places for I2C comms.

1.) Any thoughts on how I can improve the code or hardware to get this to read without missing steps?

Hardware:

- Nano (USB Powered)
- White .96" OLED I2C SSD1306
- HW-040 Rotary Encoder

Libraries:
- Arduino WIRE
- Adafruit SSD1306 Library

The Serial Monitor Code:

```

#define PinCLK 2
#define PinDT 3

volatile boolean turnDetected = false;
void rotarydetect() {
  turnDetected = true;
}

void setup() {
  attachInterrupt (digitalPinToInterrupt(2), rotarydetect, CHANGE);
  pinMode(PinCLK, INPUT_PULLUP);
  pinMode(PinDT, INPUT_PULLUP);
  Serial.begin(2000000);
}

void loop() {
  if(turnDetected) {
    turnDetected = false;

    static uint8_t enc_val = 0;
    static int16_t enc_count = 0;
    static int8_t lookup_table[] = {0,1,0,-1,-1,0,1,0,0,1,0,-1,-1,0,1,0};
    static long lastTimeToDebounce = 0;
    static int debounceTime = 1;
    static int enc_counter = 0;

    if((millis() - lastTimeToDebounce) > debounceTime) {

    enc_val <<= 2;
    enc_val = enc_val | ((PIND & 0b1100) >> 2);
    enc_counter = enc_counter + lookup_table[enc_val & 0b1111];

    Serial.print("Counter: ");
    Serial.println(enc_counter);
    Serial.println("");
    }
    lastTimeToDebounce = millis();
  }
}
```

And the OLED Code:

```

#include <SPI.h>
#include <Wire.h>
#include <Adafruit_SSD1306.h>

#define SCREEN_WIDTH 128 // OLED display width, in pixels
#define SCREEN_HEIGHT 64 // OLED display height, in

#define PinCLK 2
#define PinDT 3

Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, -1);

volatile boolean rotated = false;

void rotarydetect() {
  rotated = true;
}

void setup() {
  Wire.begin();
  Wire.setClock(400000);
  attachInterrupt (digitalPinToInterrupt(2), rotarydetect, CHANGE);
  pinMode(PinCLK, INPUT_PULLUP);
  pinMode(PinDT, INPUT_PULLUP);

  display.begin(SSD1306_SWITCHCAPVCC, 0x3C);
  display.setTextSize(1);
  display.setTextColor(SSD1306_WHITE);
}

void loop() {
  if(rotated) {
    rotated = false;

    static uint8_t enc_val = 0;
    static int16_t enc_count = 0;
    static int8_t lookup_table[] = {0,1,0,-1,-1,0,1,0,0,1,0,-1,-1,0,1,0};
    static long lastTimeToDebounce = 0;
    static int debounceTime = 3;
    static int enc_counter = 0;

    if((millis() - lastTimeToDebounce) > debounceTime) {

    enc_val <<= 2;
    enc_val = enc_val | ((PIND & 0b1100) >> 2);
    enc_counter = enc_counter + lookup_table[enc_val & 0b1111];
    display.setCursor(0,0);
    display.clearDisplay();
    display.print("Counter: ");
    display.println(enc_counter);
    display.println("");
    display.display();

    }
    lastTimeToDebounce = millis();
  }
}
```

I also tried the LCD_1602 screen (still through the I2C module board), and more or less it has the same results.  I also switched the code from the ISR to trigger the code loop, to a polling loop that detects when the CLK pin changes state with the LCD 1602 screen.  Same array with bit shifting as above for state detection.  Same results.  I also removed the very low debouncing code altogether with the Wire.setClock(400000) same results.

Seems like this may be a I2C limitation for communication?

title: Different Counter Reading on Serial Monitor Vs .96" OLED I2C

Answers: 0


body:
I used a DHT 11 sensor with an Arduino Uno to measure temperature and humidity. I used the following code to print the temperature and relative humidity in Serial Monitor.
```
dht DHT;

#define DHT11_PIN 7

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

void loop()
{
  int chk = DHT.read11(DHT11_PIN);
  delay(1000);
  Serial.print(DHT.temperature);
  Serial.print(" , ");
  Serial.println(DHT.humidity);
  delay(1000);
}
```
The Serial monitor printed the following data values in a list in the order of: time, temperature (Celsius), humidity (percentage).
```
22:17:55.686 -> 25.00 , 55.00
22:17:57.713 -> 25.00 , 55.00
22:17:59.741 -> 25.00 , 54.00
22:18:01.769 -> 25.00 , 54.00
22:18:03.793 -> 25.00 , 55.00
22:18:05.813 -> 25.00 , 54.00
22:18:07.837 -> 25.00 , 54.00
22:18:09.868 -> 25.00 , 55.00
22:18:11.880 -> 25.00 , 55.00
22:18:13.900 -> 25.00 , 55.00
22:18:15.915 -> 25.00 , 56.00
22:18:17.950 -> 25.00 , 56.00
22:18:19.972 -> 25.00 , 56.00
22:18:21.994 -> 25.00 , 56.00
22:18:24.024 -> 25.00 , 56.00
22:18:26.043 -> 25.00 , 56.00
22:18:28.093 -> 25.00 , 55.00
22:18:30.122 -> 25.00 , 55.00
22:18:32.141 -> 25.00 , 55.00
22:18:34.142 -> 25.00 , 55.00
```
I used the PuTTY software to save the sensor data to a CSV file. However, I end up with a few strange numbers at the top before the values start printing properly.
```
25.25.00 , 53.00
25.00 , 53.00
25.00 , 53.00
25.00 , 53.00
25.00 , 53.00
25.00 , 53.00
25.00 , 53.00
25.00 , 53.00
25.00 , 53.00
25.00 , 53.00
25.00 , 53.00
25.00 , 53.00
25.00 , 53.00
25.00 , 53.00
25.00 , 53.00
25.00 , 53.00
25.00 , 53.00
25.00 , 53.00
25.00 , 53.00
```
Also, when I open the CSV file in Excel, the time values have disappeared, even though they were there in the serial monitor.
[![Excel Spreadsheet][1]][1]

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

What can I do to get the time stamps to show up in my spreadsheet? Additionally, is there a way I can have the graph automatically update as more data is read?

title: How do I generate a graph from Arduino sensor data?

Answers: 1

body:
Perhaps the built-in Arduino Serial Plotter is all you need to visualize your data.  I wrote a [tutorial][1] a while back that might help you.

  [1]: https://www.woolseyworkshop.com/2019/05/03/using-the-arduino-serial-plotter-to-visualize-real-time-data/


body:
I am trying to interface Arduino UNO with Cirus OS1 oxygen sensor but not able to get the expected output. The expected voltage output of OS1 sensor is 9-13mV and the oxygen % is expected to be in the range 19-21 %.

I am using the code :

```cpp
void setup()

{

     Serial.begin(9600);
     analogReference(INTERNAL);
}

void loop()
{

     const float A_REF = 1.1e3;
     const float Sensor_Cal = 1 / 0.6;
     int sensorValue = analogRead(A0);
     float voltage = sensorValue *(A_REF / 1024);
     float oxygen = voltage * Sensor_Cal;
     Serial.print(" Voltage in mV : ");
     Serial.print(voltage);
     Serial.print("  ");
     Serial.print(" Oxygen level in % : ");
     Serial.println(oxygen);
     delay(1000);
}
```

However, I am getting an output :

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

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

I am using Cirus OS1 oxygen sensor - https://www.biometriccables.in/collections/oxygen-sensors/products/oxygen-sensor-os1

Expected voltage range - 9mV to 13mV
Expected oxygen % - 19 to 21 %
Have tried using LM324N opamp, but it's still not giving expected output. Kindly help or suggestions are welcome.

title: Problem with interfacing Cirus OS1 oxygen sensor with Arduio Uno

Answers: 0


body:
I am using Websocket, for a communication from my mobile phone to a NodeMCU, and transmitting 4 channel, data, through 4 different Websocket Ports.
the NodeMCU control code is here:

```
// ============ By Pritam Pagla ============ //
// The Only Websocket Program is attached within master branch

// NodeMCU SIDE

#include <SoftwareSerial.h>
#include <ArduinoJson.h>     // Preferably use ArduinoJson 5.x, as StaticJsonBuffer object is not defined in further versions
#include <ESP8266WiFi.h>
#include <ESP8266WebServer.h>
#include<WebSocketsServer.h>

#include "index_NodeMCU_Test1.h";   // Complete Webpage

SoftwareSerial s(D6,D5);          // Rx as D6 and Tx and D5

int16_t throttle_Val = 0;
int16_t yaw_Val = 0;
int16_t pitch_Val = 0;
int16_t roll_Val = 0;

uint8_t num;
WStype_t type;
uint8_t *payload;
size_t length;

//WiFi Connection configuration
const char *ssid = "PriCopter";       // Can choose these anything one wants
const char *password = "01234567";

WebSocketsServer Twebsocket = WebSocketsServer(9001);
WebSocketsServer Ywebsocket = WebSocketsServer(9002);
WebSocketsServer Rwebsocket = WebSocketsServer(9003);
WebSocketsServer Pwebsocket = WebSocketsServer(9004);

ESP8266WebServer server(80);

//================================================

void handleRoot() {
 String s = MAIN_page; //Read HTML contents
 server.send(200, "text/html", s); //Send web page
}

//================================================
//            Setup
//================================================

void setup() {
s.begin(115200);
Serial.begin(115200);
 delay(100);

  //Setup the NodeMCU as an AP
  WiFi.softAP(ssid, password, 1, false, 1);    //Use NodeMCU as an access point

  //If connection successful show IP address in serial monitor
  IPAddress IP = WiFi.softAPIP();
  Serial.print("AP IP address: ");
  Serial.println(IP);

  //Initialize Webserver
  server.on("/",handleRoot);

  server.begin();
  Twebsocket.begin();
  Ywebsocket.begin();
  Rwebsocket.begin();
  Pwebsocket.begin();

}

void loop() {
 StaticJsonBuffer<100> jsonBuffer;
 JsonObject& root = jsonBuffer.createObject();

 server.handleClient();
 Twebsocket.loop();
 Ywebsocket.loop();
 Rwebsocket.loop();
 Pwebsocket.loop();

 Twebsocket.onEvent(ThrottleEvent);
 Ywebsocket.onEvent(YawEvent);
 Rwebsocket.onEvent(RollEvent);
 Pwebsocket.onEvent(PitchEvent);

 Serial.print("Throttle:  "); Serial.print(throttle_Val);
 Serial.print("   Yaw:  "); Serial.print(yaw_Val);
 Serial.print("   Pitch:  "); Serial.print(pitch_Val);
 Serial.print("   Roll:  "); Serial.print(roll_Val);

  root["throttle"] = throttle_Val;
  root["yaw"] = yaw_Val;
  root["roll"] = pitch_Val;
  root["pitch"] = roll_Val;

 root.printTo(s);
 Serial.println("   (Sent)");
}

void YawEvent(uint8_t num, WStype_t type, uint8_t *payload, size_t length){
  if (type == WStype_TEXT){
      yaw_Val = (int16_t)strtol((const char*) &payload[0], NULL, 10);
  }
}

void ThrottleEvent(uint8_t num, WStype_t type, uint8_t *payload, size_t length){
  if (type == WStype_TEXT){
      throttle_Val = (int16_t)strtol((const char*) &payload[0], NULL, 10);
  }
}

void RollEvent(uint8_t num, WStype_t type, uint8_t *payload, size_t length){
  if (type == WStype_TEXT){
      roll_Val = (int16_t)strtol((const char*) &payload[0], NULL, 10);
  }
}

void PitchEvent(uint8_t num, WStype_t type, uint8_t *payload, size_t length){
  if (type == WStype_TEXT){
      pitch_Val = (int16_t)strtol((const char*) &payload[0], NULL, 10);
  }
}
```

and requiring Webpage details is as:

```
const char MAIN_page[] PROGMEM = R"=====(<!DOCTYPE html>
<html lang = 'en'>
  <head>
    <meta charset="UTF-8"/>
    <meta name="viewport"
    content="width=950, height=420 initial-scale=1.0"/>
    <meta http-equiv="X-UA-Compatible"
    content="ie=edge"/>
    <title>Drone Remote</title>
    <style>
    body{
      background-color: #333;
      color: 'black';
      display: flex;
      flex-direction: row;
      align-items: center;
      font-family: Arial, Helvetica, sans-serif;
      min-height: 100vh;
      margin:0;
    }
    #canvasL{
      background: #f0f0f0;
      border-radius: 5x
    }
    #canvasM{
      background: #f0f0f0;
      border-radius: 5px
    }
    #canvasR{
      background: #f0f0f0;
      border-radius: 5px
    }

    #source{
      display: none;
    }

    </style>
  </head>
  <body>
    <canvas id="canvasL" width="450" height="420"></canvas>
    <canvas id="canvasM" width="50" height="420"></canvas>
    <canvas id="canvasR" width="450" height="420"></canvas>

    <img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADIAAAAyCAYAAAAeP4ixAAAHWElEQVRoQ7WZT2xUVRTGv9vptIBAC6ghbtQYEhtD4kLcsJCNUdOtLUldGKOuujH+STQYDcGQKEFWGv8LIQgMqcrG6AZcGEkwxEjShUFJVxAIaEVsC23nmnN7v+mZM/fOvJm2L3m5b968ee/87vedc++747BC2/vA1iqwfR54aA6Y98CvM8DP7wAXVuKRbjlu+iXQXwX+rgLwAKSVfQ7AfNzleDae0y2ANQeA6aXGsSSQIwuxdUsQ3jls3b0brlRC1fsFIO9r+3w8FjA5PzM9jVP79oUbyH4buPEp0NcpUEcgFYkbgOwP7toF19UFHwOVNgvhfVBoTlq1/zs5iZ8OHhQY2ecPx85pB6otkDHgRwc81gVg8+Ag1g8MABK4Cj4cxyCpSLCX9wFAzhFEWrFcaL3H+KlTuHTxYgCaBV6tAPuLwhQG+QbwJQCy3zc6Cud9gCCIPDBYihZSVmLvM+AApQB4/rb3uD07izNjYwFG8qyyIHzLrchF7iRQlUSQ/Z6REZR6eupArCrMB/a8BDQbVWLQ0oaklzYqIq3A/HnuHK5evhy+l60ITFOQr4FN3cC1coQQNTYPD6PL+wBCVSQnqISoov2f6nlCSODcCRRgAJw/fTq0cu8iMFmQCtCzCrglEAQRRe4cHFwECeUq5oiylM4JgdI9rlWgAgIhSoTqFY9/P3s2gMi9uDVTJgvyLeAFoCeCSCsg/Tt2BBBJ+JoiqmIFOxn/13o+WowAPB+qFWG8xy3vMTE+zqSvy48cTBJkDPC9CoAwArZ+2zaUoq0EhoqwQulKpK3D4ENFikEz+NAqGPl8aWICtxbKccOWgmkAOQZUVwGOIA1A3d1YvWVLqF6ijAZJQQTLxF7W1pFeJ0gIOH6W89evXq1ByHfME0X0QwV4UhM2gJyIagiAKCG7PhZVejdsQHnduqAMQcROtvpIcBIIFUgFz3PTEeTm1BRmqtU6EKl6drOq1IEcBTwDZ/C2JZzkS3njxpAnYV4VS6gERgXEFjr4mahMOBe/k2OeF4BwPu481gmvgTRMA4gEzl1D5YCcc5grlxeDVxYJATFoFaANlJ+ZE/qzHLcFcihayiqyKtqLrYUUZWwA0pMzMVHZ2mBT59sF0eNLTREBySmQUogWk8olg17KErme16C29/V9+F1OkQaQj4G/eoEN2j72WCc8y7GoIT0Rxo0IE2ewdSrZ4Cx0Tr1WOSIgDnj0OPBLUOSjjK1SlUuP9FKC5QaS7KFqLb5bcEpeA8oFn7KTBU9VLZv0AeRDU3ItAEd4rQRnwmFMVG+C8SWpNiqH8mvyiIGm4ORamz+JcaRhtHcecB8AVRt8bmTXE0gmGF9vaTGrjAZJWU+rksq1xDDSCLIf2FsG3rA5oOdYnGdpCNqKd6S9wmzX2EyrRBCriv6siwGn8s1g5oEB966qVtpCdQNfnHfJ97RUmDTGPbXgoBcY4htfLW9SMDmwZhVLwR1yeyMIA9dKMLH1NN6CMEesvawyNndyMNZarfKDMG6PAmHgKTUEQMptmCzGXU8LuASkl4G0xZg31mbMn1RBKGKrGsjbRhGrglZDAARG20rnCKsXYagKxxjaTavRLH9ald262e+b8QVK50eYEMag+a5OACrC/ODNdJ7oRTkNY1XJ2Y0lu1W1qgN53YBIwKxSErROcOaHQISXKpXs4b1dDY4pGA2iS3QKqGCSk+WMewX4vgw8oUusVYMANj/0OGJB7JJparmUABakndyIJI8LyL0OmLCLDFSCCW4hqIiWVye8Hlf0QJmrZlqhopWKz5b3ktCpLwGeuWBLbQ6EakjLB+tFbFpLW4zzsVw1E5g2LRVYaiCjCRDayZZcViyriLZWqhRTFa0IqxnbTiDqQF6MCa8rlAaRoDkl4RjCRNdVy8KkVOFfDbSS/ruhnSqlrr1WAe4KDhkCSn3AnM0LW3L1QGhXLQhhyzBzhYrYfOnUTjo/6jr1WWUvXaV0kmtbtQJJlWJrL6rToRK1/KgDGQE+KwHP6+TW8yqqkRrV9XyLAHqU1xbT1mq3OlngMtB3BLhhbY6dURUNkJrt6sEwlyMaJGWvpahgbZUCec4DX4htUvmhR/Rc1UpVL63IcgDIPXqBtYeB/3i/hpXGYbVCycBTtkotGmsIm/TLBZBSo0ERXqRhNDEninbCaO3FgXG5g89BZEGGgI0OuL5SgSzlvm39rRDHFlkremQpD13u33YBLxwDPk/dt+lfb0PAFQfcXTSg1H8ZzX4rM+6imwe+OgE8k7u+KYj8aCfwhwceaPbAm0WjyVy3tvXv36oAe5pd1hIk2ux+B1xM3WiydRCFrujPXNUP9HyysMbXdCsEwjukqtlyVYRNiTCL/C3Nn7UFEtV5zQHv6eeKKi27LNOfawDcYb5zwMPHgd9aqaC/bxuEPx4CvnPAU/Zh/8R13mZBSPCZvHi5AhxoB6BjRexDhoDVDpjq5OH8zQBQ2r2wqN/x1rEiuScOA9s9cNIBKdvLa/GFbuDpo8D5jqNO/PB/ioZ2+ax3loAAAAAASUVORK5CYII=" alt="" id="source"/>
    <script>
    const canvasL = document.getElementById('canvasL');       // Object for left canvas
const Lctx = canvasL.getContext('2d');

const canvasM = document.getElementById('canvasM');       // Object for Middle canvas
const Mctx = canvasM.getContext('2d');

const canvasR = document.getElementById('canvasR');       // Object for Right canvas
const Rctx = canvasR.getContext('2d');

const LcenterX = (canvasL.width / 2);    // Marking centre for left Joystick
const LcenterY = (canvasL.height / 2);
const RcenterX = (canvasR.width / 2);    // Marking centre for Right Joystick
const RcenterY = (canvasR.height / 2);
const McenterX = (canvasM.width / 2);    // Marking centre for Middle Portion
const McenterY = (canvasM.height / 2);

var Tsocket = new WebSocket('ws://' + window.location.hostname + ':9001/');
var Ysocket = new WebSocket('ws://' + window.location.hostname + ':9002/');
var Psocket = new WebSocket('ws://' + window.location.hostname + ':9003/');
var Rsocket = new WebSocket('ws://' + window.location.hostname + ':9004/');

const image = document.getElementById('source');

var throttle_Val = 0;
var yaw_Val = 0;
var pitch_Val = 0;
var roll_Val = 0;

const throttle = "t";
const yaw = "y";
const pitch = "p";
const roll = "r";

const LJoyStickBall = {         // defining left joystick as an object
  w: 60,
  h: 60,
  x: LcenterX,
  y: LcenterY+195,
  speed: 1,
  dx: 0,
  dy: 0
};
const RJoyStickBall = {         // defining right joystick as an object
  w: 60,
  h: 60,
  x: RcenterX,
  y: RcenterY,
  speed: 1,
  dx: 0,
  dy: 0
};

function drawLeftCenterBall(){      //Drawing the Left Joystick ball
  Lctx.drawImage(image, LJoyStickBall.x-30, LJoyStickBall.y-30, LJoyStickBall.w, LJoyStickBall.h);
}
function drawRightCenterBall(){      //Drawing the Right Joystick ball
Rctx.drawImage(image, RJoyStickBall.x-30, RJoyStickBall.y-30, RJoyStickBall.w, RJoyStickBall.h);
}

function LnewPos() {                    // changing position for keyboard activity
  LJoyStickBall.x += LJoyStickBall.dx;
  LJoyStickBall.y += LJoyStickBall.dy;

  LdetectBoundary();
}

function RnewPos() {                    // changing position for keyboard activity
  RJoyStickBall.x += RJoyStickBall.dx;
  RJoyStickBall.y += RJoyStickBall.dy;

  RdetectBoundary();
}

function LdetectBoundary(){             // defining the boundary for the LeftJoystickCenterBall
  // Left side
  if (LJoyStickBall.x < LcenterX-195) {
    LJoyStickBall.x = LcenterX-195;
  }

  // Right side
  if (LJoyStickBall.x > LcenterX+195) {
    LJoyStickBall.x = LcenterX+195;
  }

  // Top side
  if (LJoyStickBall.y < LcenterY-195) {
    LJoyStickBall.y = LcenterY-195;
  }

  // Bottom side
  if (LJoyStickBall.y > LcenterY+195) {
    LJoyStickBall.y = LcenterY+195;
  }
}

function RdetectBoundary(){             // defining the boundary for the LeftJoystickCenterBall
  // Left side
  if (RJoyStickBall.x < RcenterX-195) {
    RJoyStickBall.x = RcenterX-195;
  }

  // Right side
  if (RJoyStickBall.x > RcenterX+195) {
    RJoyStickBall.x = RcenterX+195;
  }

  // Top side
  if (RJoyStickBall.y < RcenterY-195) {
    RJoyStickBall.y = RcenterY-195;
  }

  // Bottom side
  if (RJoyStickBall.y > RcenterY+195) {
    RJoyStickBall.y = RcenterY+195;
  }
}

function drawDesigns(){               // 4 Convrntric circles and 2 crossed st lines for better interface
  Lctx.beginPath();
  Lctx.lineWidth = 2.5;
  Lctx.moveTo(LcenterX, LcenterY-195);    // Crossing lines on left
  Lctx.lineTo(LcenterX, LcenterY+195);
  Lctx.moveTo(LcenterX-195, LcenterY);
  Lctx.lineTo(LcenterX+195, LcenterY);
  Lctx.arc(LcenterX, LcenterY, 195, 0, Math.PI * 2);   //Concentric circles on Left
  Lctx.arc(LcenterX, LcenterY, 150, 0, Math.PI * 2);
  Lctx.arc(LcenterX, LcenterY, 100, 0, Math.PI * 2);
  Lctx.arc(LcenterX, LcenterY, 50, 0, Math.PI * 2);
  Lctx.stroke();

  Rctx.beginPath();
  Rctx.lineWidth = 2.5;
  Rctx.moveTo(RcenterX, RcenterY-195);    // Crossing lines on Right
  Rctx.lineTo(RcenterX, RcenterY+195);
  Rctx.moveTo(RcenterX-195, RcenterY);
  Rctx.lineTo(RcenterX+195, RcenterY);
  Rctx.arc(RcenterX, RcenterY, 195, 0, Math.PI * 2);   //Concentric circles on Right
  Rctx.arc(RcenterX, RcenterY, 150, 0, Math.PI * 2);
  Rctx.arc(RcenterX, RcenterY, 100, 0, Math.PI * 2);
  Rctx.arc(RcenterX, RcenterY, 50, 0, Math.PI * 2);
  Rctx.stroke();
}
function clearScreen(){             // Clearing the LeftCanvas and RightCanvas on every loop of the Animation
  Lctx.clearRect(0, 0, canvasL.width, canvasL.height);
  Rctx.clearRect(0, 0, canvasR.width, canvasR.height);
}

function ConsoleOUT(a,b,c,d){
   throttle_Val = (405-a);
   yaw_Val = (b-225);
   pitch_Val = (210-c);
   roll_Val = (d-225);
  console.log('Throttle: '+throttle_Val+'    Yaw: '+yaw_Val+'    Pitch: '+pitch_Val+'    Roll: '+roll_Val);
}

function LeftUpdate(){
  clearScreen();                                //Left Joystick
  drawDesigns();
  drawLeftCenterBall();
  drawRightCenterBall();
  LnewPos();
  RnewPos();
  ConsoleOUT(LJoyStickBall.y,LJoyStickBall.x,RJoyStickBall.y,RJoyStickBall.x);
  requestAnimationFrame(LeftUpdate);

}
function RightUpdate(){                                 //Right Joystick
  clearScreen();
  drawDesigns();
  drawLeftCenterBall();
  drawRightCenterBall();
  LnewPos();
  RnewPos();
  ConsoleOUT(LJoyStickBall.y,LJoyStickBall.x,RJoyStickBall.y,RJoyStickBall.x);
  requestAnimationFrame(RightUpdate);
}

function LmoveUp() {                          // For KeyboardActivity
  LJoyStickBall.dy = -LJoyStickBall.speed;
}

function LmoveDown() {
  LJoyStickBall.dy = LJoyStickBall.speed;
}

function LmoveRight() {
  LJoyStickBall.dx = LJoyStickBall.speed;
}

function LmoveLeft() {
  LJoyStickBall.dx = -LJoyStickBall.speed;
}
function RmoveUp() {
  RJoyStickBall.dy = -RJoyStickBall.speed;
}

function RmoveDown() {
  RJoyStickBall.dy = RJoyStickBall.speed;
}

function RmoveRight() {
  RJoyStickBall.dx = RJoyStickBall.speed;
}

function RmoveLeft() {
  RJoyStickBall.dx = -RJoyStickBall.speed;
}

canvasL.addEventListener('touchstart', function(e){         // 'touchstart' event in LeftCanvas
       e.preventDefault();
       canvasL.addEventListener('touchmove', function(e){
              var touchobj = e.touches[0]; // reference first touch point for this event
              LJoyStickBall.x = touchobj.pageX;
              LJoyStickBall.y = touchobj.pageY;
              sendData(throttle,405-LJoyStickBall.y);
              sendData(yaw,LJoyStickBall.x-225);
              }, false)
   }, false)

   canvasL.addEventListener('touchend', function(e){            // 'touchend' event in LeftCanvas
       e.preventDefault();
       LJoyStickBall.x = LcenterX;
       sendData(yaw,0);
    }, false)

canvasR.addEventListener('touchstart', function(e){         // 'touchstart' event in RightCanvas
       e.preventDefault();
       canvasR.addEventListener('touchmove', function(e){
              var touchobj = e.touches[0]; // reference first touch point for this event
              RJoyStickBall.x = touchobj.pageX - (canvasR.width + RJoyStickBall.w);
              RJoyStickBall.y = touchobj.pageY - RJoyStickBall.h;
              sendData(pitch,210-RJoyStickBall.y);
              sendData(roll,RJoyStickBall.x-225);

          }, false)
   }, false)

   canvasR.addEventListener('touchend', function(e){            // 'touchend' event in RightCanvas
       e.preventDefault();
       RJoyStickBall.x = RcenterX;
       RJoyStickBall.y = RcenterY;
       sendData(pitch,0);
       sendData(roll,0);
      }, false)

  function sendData(a,b){

    if(a == throttle){
      Tsocket.send(b);
    }
    if(a == yaw){
      Ysocket.send(b);
    }
    if(a == roll){
      Rsocket.send(b);
    }
    if(a == pitch){
      Psocket.send(b);
    }

    // switch(a){

    //   case throttle:
    //     Tsocket.send(b);
    //     break;
    //   case yaw:
    //     Ysocket.send(b);
    //     break;
    //   case roll:
    //       Rsocket.send(b);
    //       break;
    //   case pitch:
    //       Psocket.send(b);
    //       break;
    //   default:
    //     console.log('Interruption Occured.')
    // }
  }

  document.addEventListener('keydown', function (e) {        // When certain key is pressed down
    if (e.key == 'ArrowRight') {
      LmoveRight();
      sendData(yaw,LJoyStickBall.x-225);
    } if (e.key == 'ArrowLeft') {
      LmoveLeft();
      sendData(yaw,LJoyStickBall.x-225);
    } if (e.key == 'ArrowUp') {
      LmoveUp();
      sendData(throttle,405-LJoyStickBall.y);
    } if (e.key == 'ArrowDown') {
      LmoveDown();
      sendData(throttle,405-LJoyStickBall.y);
    }
    if(e.key == 'w'){
      RmoveUp();
      sendData(pitch,210-RJoyStickBall.y);
    }
    if(e.key == 's'){
      RmoveDown();
      sendData(pitch,210-RJoyStickBall.y);
    }
    if(e.key == 'a'){
      RmoveLeft();
      sendData(roll,RJoyStickBall.x-225);
    }
    if(e.key == 'd'){
      RmoveRight();
      sendData(roll,RJoyStickBall.x-225);
    }
  });
   document.addEventListener('keyup', function (e) {        // When certain key is released
    if (
      e.key == 'ArrowLeft' ||
      e.key == 'ArrowRight' ||
      e.key == 'ArrowUp' ||
      e.key == 'ArrowDown' ||
      e.key == 'w' ||
      e.key == 's' ||
      e.key == 'a' ||
      e.key == 'd'
    ) {
      LJoyStickBall.dx = 0;
      LJoyStickBall.dy = 0;
      RJoyStickBall.dx = 0;
      RJoyStickBall.dy = 0;
      LJoyStickBall.x = LcenterX;
      RJoyStickBall.x = RcenterX;
      RJoyStickBall.y = RcenterY;
      sendData(yaw,0);
      sendData(pitch,0);
      sendData(roll,0);
    }
  });

  LeftUpdate();
  RightUpdate();
    </script>
  </body>
</html>

)=====";
```

Now, I am new to Web based projects and clearly new to Websockets. In the beginning, i used single websocket port and transmitted the data of the four channels as JSON file, but differentiating the data in 4 different channels, increased the speed slighly, but still one problem is consistent throughout, i.e. after a few seconds, (30-35), it starts to achieve latency, and it stays untill the page is not refreshed again.
Can someone please suggest any solution for this, as I am using this for controlling my drone, therefore, any unnecessary latency can be dangerous.

For further information, you can see detailed description and similar codes in this [repo](https://github.com/Pritam-Pagla/Drone-Control).

Thanks in advance.

title: Latency in Websocket

Answers: 1

body:
Not really a proper answer, but a few ideas that hopefully could help
you debug the issue:

* I doubt using multiple WebSocket servers really helps, as you end up
  adding more context switching, i.e. you have to loop through all of
  them even when they have no data to process.
* `SoftwareSerial` tends to be really slow, as it blocks execution of
  the sketch while it is sending. You may try to disable it, at least
  while you troubleshoot this latency issue.
* Calling `Serial.print()` on every loop iteration is also going to slow
  the sketch down until it is no faster than the serial port. Try to
  print only once in a while, or only when things actually change.
* Both Firefox and Chrome have “developer tools” which should help you
  diagnose the problem. At the very least you should be able to see
  whether the slowdown comes from the server or from the client.


body:
Quick query (I hope).

I have an Arduio R3 board with ATMega328P U on board. It works fine. I bought some new MCUs, ordered **with bootloader**. Same IC designation. Before I dive into my new project I want to confirm they are okay.

So ...............I take the original MCU out of the Arduino R3 and replace it with a new ATMega328P U. Should it work fine straight away? i.e. can I upload simple sketches like Blink?

My problem is that I've done this and none of them work. I get two flashes on the Rx LED on the board, then ArvDude gives me a string of "not in sync" error messages. If I put the original MCU back in then everything works okay again. I don't want to go through the hassle of burning bootloader on chips that supposedly have it, I'd rather send them back.

Are my new MCUs duff? Or is there any other easy way to check them?

Many thanks

title: ATMega328P U Query - does it work straight away on Uno R3

Answers: 1

body:
The MCU on the Uno R3 comes with a specific bootloader (Optiboot) and
fuse configuration (external clock, clock prescaler disabled, bootloader
enabled...). You may find some ATmega328Ps on the market that have been
specifically configured as drop-in replacements for the one on an Uno.
Those should “just work”. If the ones you bought come with a different
bootloader or fuse configuration, you may have to re-flash or
reconfigure them.


body:
i have simple circuit for controlling the dc motor by bjt BC869 like this:

[![pro][1]][1]
and this code:

```
/*
  ESP8266 Blink by Simon Peter
  Blink the blue LED on the ESP-01 module
  This example code is in the public domain

  The blue LED on the ESP-01 module is connected to GPIO1
  (which is also the TXD pin; so we cannot use Serial.print() at the same time)

  Note that this sketch uses LED_BUILTIN to find the pin with the internal LED
*/
#define dd 1
void setup() {
  pinMode(LED_BUILTIN, OUTPUT);     // Initialize the LED_BUILTIN pin as an output
   pinMode(dd, OUTPUT);     // Initialize the LED_BUILTIN pin as an output
}

// the loop function runs over and over again forever
void loop() {
  digitalWrite(LED_BUILTIN, LOW);   // Turn the LED on (Note that LOW is the voltage level
  // but actually the LED is on; this is because
  // it is active low on the ESP-01)
  delay(1000);                      // Wait for a second
  digitalWrite(LED_BUILTIN, HIGH);  // Turn the LED off by making the voltage HIGH
  delay(2000);
//  loop1() ;// Wait for two seconds (to demonstrate the active low LED)
}
void loop1() {
  digitalWrite(dd, LOW);   // Turn the LED on (Note that LOW is the voltage level
  // but actually the LED is on; this is because
  // it is active low on the ESP-01)
  delay(1000);                      // Wait for a second
  digitalWrite(dd, HIGH);  // Turn the LED off by making the voltage HIGH
  delay(2000);                      // Wait for two seconds (to demonstrate the active low LED)
}
```
it was working days before but it stopped from working by connecting to prototype circuit by breadboard, but after connecting to this circuit it programmed for two  or three times and after that it showing this error:

[![Arduino][2]][2]

```
Executable segment sizes:
IROM   : 227612          - code in flash         (default or ICACHE_FLASH_ATTR)
IRAM   : 26768   / 32768 - code in IRAM          (ICACHE_RAM_ATTR, ISRs...)
DATA   : 1252  )         - initialized variables (global, static) in RAM/HEAP
RODATA : 672   ) / 81920 - constants             (global, static) in RAM/HEAP
BSS    : 24880 )         - zeroed variables      (global, static) in RAM/HEAP
Sketch uses 256304 bytes (26%) of program storage space. Maximum is 958448 bytes.
Global variables use 26804 bytes (32%) of dynamic memory, leaving 55116 bytes for local variables. Maximum is 81920 bytes.
esptool.py v2.8
Serial port /dev/ttyUSB1
Connecting........_____....._____.
Chip is ESP8266EX
Features: WiFi
Crystal is 26MHz
MAC: d8:bf:c0:ff:6f:30
Uploading stub...
Running stub...
Stub running...
Configuring flash size...
Auto-detected Flash size: 4MB
Flash params set to 0x0340
Compressed 260464 bytes to 190649...
Writing at 0x00004000... (16 %)Traceback (most recent call last):
  File "/home/so/snap/arduino/41/.arduino15/packages/esp8266/hardware/esp8266/2.6.3/tools/upload.py", line 65, in <module>
    esptool.main(cmdline)
  File "/home/so/snap/arduino/41/.arduino15/packages/esp8266/hardware/esp8266/2.6.3/tools/esptool/esptool.py", line 2938, in main
    operation_func(esp, args)
  File "/home/so/snap/arduino/41/.arduino15/packages/esp8266/hardware/esp8266/2.6.3/tools/esptool/esptool.py", line 2374, in write_flash
    esp.flash_defl_block(block, seq, timeout=DEFAULT_TIMEOUT * ratio * 2)
  File "/home/so/snap/arduino/41/.arduino15/packages/esp8266/hardware/esp8266/2.6.3/tools/esptool/esptool.py", line 104, in inner
    return func(*args, **kwargs)
  File "/home/so/snap/arduino/41/.arduino15/packages/esp8266/hardware/esp8266/2.6.3/tools/esptool/esptool.py", line 672, in flash_defl_block
    self.ESP_FLASH_DEFL_DATA, struct.pack('<IIII', len(data), seq, 0, 0) + data, self.checksum(data), timeout=timeout)
  File "/home/so/snap/arduino/41/.arduino15/packages/esp8266/hardware/esp8266/2.6.3/tools/esptool/esptool.py", line 379, in check_command
    raise FatalError.WithResult('Failed to %s' % op_description, status_bytes)
esptool.FatalError: Failed to write compressed data to flash after seq 1 (result was C100)
esptool.FatalError: Failed to write compressed data to flash after seq 1 (result was C100)

```

So i have seen some suggestion like changing the USB port and dont worked for me, so i like to know why this happened and how could be solved ( by flashing the esp8266 or ...)

**Update:**

I have tried by the comment suggestion this code :
`void setup() {}`
`void loop() {}`

And get again that error:
```
Executable segment sizes:
IROM   : 227372          - code in flash         (default or ICACHE_FLASH_ATTR)
IRAM   : 26360   / 32768 - code in IRAM          (ICACHE_RAM_ATTR, ISRs...)
DATA   : 1252  )         - initialized variables (global, static) in RAM/HEAP
RODATA : 672   ) / 81920 - constants             (global, static) in RAM/HEAP
BSS    : 24848 )         - zeroed variables      (global, static) in RAM/HEAP
Sketch uses 255656 bytes (24%) of program storage space. Maximum is 1044464 bytes.
Global variables use 26772 bytes (32%) of dynamic memory, leaving 55148 bytes for local variables. Maximum is 81920 bytes.
esptool.py v2.8
Serial port /dev/ttyUSB1
Connecting........_____.
Chip is ESP8266EX
Features: WiFi
Crystal is 26MHz
MAC: d8:bf:c0:ff:6f:30
Uploading stub...
Running stub...
Stub running...
Configuring flash size...
Auto-detected Flash size: 4MB
Compressed 259808 bytes to 190257...
Writing at 0x00004000... (16 %)Traceback (most recent call last):
  File "/home/so/snap/arduino/41/.arduino15/packages/esp8266/hardware/esp8266/2.6.3/tools/upload.py", line 65, in <module>
    esptool.main(cmdline)
  File "/home/so/snap/arduino/41/.arduino15/packages/esp8266/hardware/esp8266/2.6.3/tools/esptool/esptool.py", line 2938, in main
    operation_func(esp, args)
  File "/home/so/snap/arduino/41/.arduino15/packages/esp8266/hardware/esp8266/2.6.3/tools/esptool/esptool.py", line 2374, in write_flash
    esp.flash_defl_block(block, seq, timeout=DEFAULT_TIMEOUT * ratio * 2)
  File "/home/so/snap/arduino/41/.arduino15/packages/esp8266/hardware/esp8266/2.6.3/tools/esptool/esptool.py", line 104, in inner
    return func(*args, **kwargs)
  File "/home/so/snap/arduino/41/.arduino15/packages/esp8266/hardware/esp8266/2.6.3/tools/esptool/esptool.py", line 672, in flash_defl_block
    self.ESP_FLASH_DEFL_DATA, struct.pack('<IIII', len(data), seq, 0, 0) + data, self.checksum(data), timeout=timeout)
  File "/home/so/snap/arduino/41/.arduino15/packages/esp8266/hardware/esp8266/2.6.3/tools/esptool/esptool.py", line 379, in check_command
    raise FatalError.WithResult('Failed to %s' % op_description, status_bytes)
esptool.FatalError: Failed to write compressed data to flash after seq 1 (result was C100)
esptool.FatalError: Failed to write compressed data to flash after seq 1 (result was C100)

```

Thanks.

  [1]: https://i.stack.imgur.com/CIoxu.jpg
  [2]: https://i.stack.imgur.com/dp9hc.png

title: esp8266 Arduino error : esptool.FatalError: Failed to write compressed data to flash after seq 1 (result was C100)

Answers: 0


body:
I have a char array variable that has a value.
I need to send this value through LoRa. The library I use for the LoRa implementation accepts an array of uint8_t. How can I pass the value of a char[] to a uint8_t[] variable (and the opposite)?

    if (Udp.parsePacket()) {
      int udp_received = Udp.available();
      char udp_buffer[udp_received + 1];
      Udp.read(udp_buffer, udp_received);
      udp_buffer[udp_received] = '\0';

      uint8_t udp_to_lora[] = "???";
      rf95.send(udp_to_lora, sizeof(udp_to_lora));
      rf95.waitPacketSent();

    }

I need to pass the **udp_buffer** to **uint8_t udp_to_lora[]**.

title: How can I assign the value of a char array to a uint8_t array?

Answers: 1

body:
I don't have a compiler at hand, but you can cast the array  as a `char` and `uint8_t` are similar in size:

    rf95.send((char*) udp_to_lora, sizeof(udp_to_lora));


body:
I have a problem with the global variable calibrationValue. It is initially set with the correct value and is also displayed correctly in the output. As soon as the loop function is restarted, the value of the variable is wrong, although it is not rewritten. Can someone help me please?
The following values are printed in the image:
1. new AI value
2. wrong calibrationValue (!)
3. sumOfValues (needed for calculation of calibrationValue) correct
4. numValues (needed for calculation of calibrationValue) correct
5. Text and calibrationValue (correct!)

```
    int op_mode_Pin = 7;                      // Digital input Pin which transmittes the op_mode_Ardui
    int op_mode_Ardui;                        // Operator Mode of Arduino
    int returnValue1 = 12;                    // First digital return value for transmitting box weight
    int returnValue2 = 13;                    // Second digital return value for transmitting box weight

    int sensorPin = A0;                       // Select the input pin for the potentiometer
    long weightValue = 0;                     // Variable to store the value from the sensor
    long calibrationValue = 0;                // Value which is filled in calibration progress
    int numValues = 50;                       // Number of taken values for calculating an average
    int thresBoxWeight = 300;                 // Weight for separating heavy and light boxes

    unsigned long sumOfValues;                // Sum of the taken values
    unsigned long aveOfValues;                // Average of the values

    char stringBuffer[30];                    // Buffer for combining string and variables

    void setup() {
      // Initiate serial communication to screen
      Serial.begin(9600);

      // Initiate some variables
      //weightValue = 0;
      //calibrationValue = 0;
      //numValues = 50;
      //thresBoxWeight = 300;

      // Set the Input Pins for op_mode_Ardui
      pinMode(op_mode_Pin, INPUT);            // sets the digital pin 7 as input

      // Set the Output Pins for Box declaration
      pinMode(returnValue1, OUTPUT);          // sets the digital pin 12 as output
      pinMode(returnValue2, OUTPUT);          // sets the digital pin 13 as output

    }

    void loop() {
      Serial.println(analogRead(sensorPin));
      Serial.println(calibrationValue);
      // Reset of Sum and Average variables for next cycle
      sumOfValues = 0;
      aveOfValues = 0;
      op_mode_Ardui = digitalRead(op_mode_Pin);

      if (op_mode_Ardui == HIGH){
        for (int i=0; i<numValues; i++){
          weightValue = analogRead(sensorPin);                                                  // read the value from the sensor
          sumOfValues = sumOfValues + weightValue;                                              // Build the sum of all values
        }
        Serial.println(sumOfValues);
        Serial.println(numValues);

        calibrationValue = sumOfValues / numValues;
        sprintf(stringBuffer, "Calibration accomplished with value: %d", calibrationValue);     // Combine text and variable to output
        Serial.println(stringBuffer);                                                           // print text and variable to screen
        delay(3000);
      }
    }
```

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

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

title: Global variable changes its value when loop starts again

Answers: 1

body:
This:

```cpp
sprintf(stringBuffer, "Calibration accomplished with value: %d", calibrationValue);
```

is a buffer overflow: the function `sprintf()` is writing a 40-byte
string into a 30-byte buffer. Whatever happens to lie in memory right
after the buffer will be overwritten by `sprintf()`. Apparently this
happened to be `calibrationValue`. You should use
`snprintf()` rather that `sprintf()`, as the former is designed to
prevent this kind of overflows.

Or better yet, stick with `Serial.print[ln]()`:

```cpp
Serial.print("Calibration accomplished with value: ");
Serial.println(calibrationValue);
```

**Edit**: You may notice that 13108 is the same as 0x3334, which on a
little endian architecture is stored in memory as 0x34 0x33. These are
the ASCII codes for "43", which is part of what `sprintf()` wrote past
the end of the buffer.


body:
I am relatively new to Arduino and plan to power an Arduino and an L293D Motor Driver with the same 9V power supply as in the diagram below.

I tried to simulate this with Tinkercad, but it seems like Tinkercad always powers the Arduino with an extra USB Cable, so I can't test it with only 1 power supply.

Would the 9V battery power both the Arduino and the L293D in this example?

[![Tinkercad Circuit][1]][1]

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

title: Powering Arduino and L293D with the same Power Supply

Answers: 1

body:
I don't see any problem. You used the Vin for 9V, and shared grounds.

I suggest using a bypass capacitor (typically 0.1 uF) for the L293D VCC, but I don't have experience with using a L293D.

Also, you need to check if the battery can deliver enough current for both motors and the Arduino.


body:
I'm trying to get started on developing a menu system for my LCD1602. I have a Parallax 5-position switch (up,down,left,right,center) and I would like to interface the two.

I've been trying to get some code working but I'm kind of lost. I don't have a lot of recent experience with Arduino and could use some advice. I realize that there is a version of the 1602 that comes with a keypad integrated into the circuit but I don't have that model. I have a plain-jane screen and a separate 5-position switch.

I'm also aware that the easiest way to accomplish what I desire is with a resistor network and mapping the ADC values. However, I don't want to make an analog switch, I want to make a digital switch.

Is there any way I can take the pins and put them into an array and then translate that into a switch case statement?

I've tried several different ideas and nothing seems to be working. Forgive the example code, it's hacked together.

below is my code

    */

    // constants won't change. They're used here to set pin numbers:
    char buttonChar1 = 'a';     // the number of the pushbutton pin
    const int buttonPin1 = 2;
    const int buttonPin2 = 3;
    const int buttonPin3 = 4;
    const int buttonPin4 = 5;
    const int buttonPin5 = 6;
    const int ledPin =  13;      // the number of the LED pin

    // variables will change:
    int buttonState1 = 0; // variable for reading the pushbutton status
    int buttonState2 = 0;
    int buttonState3 = 0;
    int buttonState4 = 0;
    int buttonState5 = 0;
    int pinsArray[5] = {2, 3, 4, 5, 6};
    void setup() {
      // initialize the LED pin as an output:
      pinMode(ledPin, OUTPUT);
      // initialize the pushbutton pin as an input:
      pinMode(buttonPin1, INPUT);
      pinMode(buttonPin2, INPUT);
      pinMode(buttonPin3, INPUT);
      pinMode(buttonPin4, INPUT);
      pinMode(buttonPin5, INPUT);
    }

    void loop() {
      // read the state of the pushbutton value:
      buttonState1 = digitalRead(buttonPin1) == 2;
      buttonState2 = digitalRead(buttonPin2) == 3;
      buttonState3 = digitalRead(buttonPin3) == 4;
      buttonState4 = digitalRead(buttonPin4) == 5;
      buttonState5 = digitalRead(buttonPin5) == 6;
      // check if the pushbutton is pressed. If it is, the buttonState is HIGH:

      switch (pinsArray[5]) {
        case 2:    //
          digitalWrite(ledPin, HIGH);
          Serial.println("button1");
          break;
        case 3:     //
          digitalWrite(ledPin, HIGH);
          Serial.println("dim");
          break;
        case 4:    //
          Serial.println("medium");
          break;
        case 5:    //
          Serial.println("bright");
          break;
      }
      }

title: using a switch case with a 5-position switch and serial output

Answers: 3

body:
Next time align your code with ctrl-K (after selecting).

And yes, you can heavily optimize your code (for maintainability) using arrays:

Instead of

    const int buttonPin1 = 2;
    const int buttonPin2 = 3;
    const int buttonPin3 = 4;
    const int buttonPin4 = 5;
    const int buttonPin5 = 6;

use

    const int buttonPins[] = { 2, 3, 4, 5, 6 };

In software engineering it's normal to start with index 0 (such as an array index).

For the button states:

    int buttonState1 = 0; // variable for reading the pushbutton status
    int buttonState2 = 0;
    int buttonState3 = 0;
    int buttonState4 = 0;
    int buttonState5 = 0;

you can use

    boolean buttonStates[5];
    for (uint8_t buttonIndex = 0; buttonindex < 5; buttonIndex++)
    {
        buttonStates[buttonIndex]= false;
    }

Instead of setting the pin modes:

  pinMode(buttonPin1, INPUT);
  pinMode(buttonPin2, INPUT);
  pinMode(buttonPin3, INPUT);
  pinMode(buttonPin4, INPUT);
  pinMode(buttonPin5, INPUT);

Use a for loop:

    for (uint8_t buttonIndex = 0; buttonindex < 5; buttonIndex++)
    {
       pinMode(buttonPins[buttonIndex], INPUT);
    }

You can combine the two `for` loops above with one.

To read the button states:

    buttonState1 = digitalRead(buttonPin1) == 2;
    buttonState2 = digitalRead(buttonPin2) == 3;
    buttonState3 = digitalRead(buttonPin3) == 4;
    buttonState4 = digitalRead(buttonPin4) == 5;
    buttonState5 = digitalRead(buttonPin5) == 6;

Use

    for (uint8_t buttonIndex = 0; buttonindex < 5; buttonIndex++)
    {
       buttonStates[buttonIndex] = digitalRead(buttonPins[buttonIndex]) == buttonPinds[buttonIndex]) ? true : false;
    }

For the switch, I think you need to keep it as it differs per pin.

And instead of using the value 5 use e.g.:

    const uint8_t NR_OF_BUTTONS = 5;

and use the NR_OF_BUTTONS constant everywhere.

Note: I don't have a compiler at hand, so forgive me for any possible compiler errors.

Also, instead of multiple arrays (each of length NR_OF_BUTTONS), you can use an array of a struct which contain the pin number and state, but this is maybe beyond the scope of your programming knowledge. The use of arrays is already a huge improvement.

body:
Michael has already given you some excellent advice on how to clean up your code.

Your switch statement does not make much sense. You're switching based on an out-of-range index into an array of constants.

Once you've read the states of all your buttons as outlined by Michael, your loop needs to decide what to do about the state of each switch.

Is this a joystick style switch, where the user can only engage one direction at a time? Or is it possible to press 2 switches at once?

If it's a diamond arrangement of 5 switches with a switch in the middle, the user could press any combination of switches at the same time.

I'd suggest code like this:

    void loop() {
        if buttonStates[0] == HIGH {
           //code to handle button 0 (pin 2) being pressed
        }

        if buttonStates[1] == HIGH {
           //code to handle button 0 (pin 3) being pressed
        }
        //And so on for the rest of your switches.
    }

body:
When you want to perform actions in response to button presses, you
should take care of reacting to the signal _edges_ rather than _levels_.
In other words, you perform the action only when the signal changes from
`LOW` to `HIGH`, not every time you see it `HIGH`.

You should also read about button bounce, and either implement your own
debouncing or use an existing library. Below is an example using
[Bounce2][], but there are other options:

```cpp
#include <Bounce2.h>

const uint8_t pinDim    = 3;
const uint8_t pinMedium = 4;
const uint8_t pinBright = 5;

Bounce buttonDim, buttonMedium, buttonBright;

void setup() {
    buttonDim.attach(pinDim, INPUT);
    buttonMedium.attach(pinMedium, INPUT);
    buttonBright.attach(pinBright, INPUT);
}

void loop() {
    buttonDim.update();
    buttonMedium.update();
    buttonBright.update();

    if (buttonDim.rose()) {
        Serial.println("dim");
    }
    if (buttonMedium.rose()) {
        Serial.println("Medium");
    }
    if (buttonBright.rose()) {
        Serial.println("bright");
    }
}
```

You could also, as suggested in Michel Keijzers' answer, use arrays for
the pins and `Bounce` objects. While these would help streamline the
calls to `attach()` and `update()`, they will not help with the meaty
part of the code, i.e. reacting to the presses. There, I would prefer
the button to have descriptive names.

[Bounce2]: https://github.com/thomasfredericks/Bounce2


body:
I have tried to  add STM8 to arduino by [this][1] instruction :

but i have this error:

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

also my system is :

```
so@so-notebook:~$ lsb_release -a
No LSB modules are available.
Distributor ID: Ubuntu
Description: Ubuntu 18.04.4 LTS
Release: 18.04
Codename: bionic

```
Also googled the :

[**stm8tool is not available for you operating system**][3]

but don't find any result to solve ...

**Update:**

based of comments :

```
so@so-notebook:~$ uname -a
Linux so-notebook 5.6.9-050609-generic #202005051753 SMP Tue May 5 22:00:17 UTC 2020 x86_64 x86_64 x86_64 GNU/Linux

```
Thanks.

  [1]: https://tenbaht.github.io/sduino/
  [2]: https://i.stack.imgur.com/PX7M3.png
  [3]: https://www.google.com/search?sxsrf=ALeKk03Zxf62_UH3iXANzkz5ImII-__6Zg:1594909453538&ei=DWMQX-63IMq0kgWB-YOwCg&q=stm8tool is not available for you operating system&oq=stm8tool is not available for you operating system&gs_lcp=CgZwc3ktYWIQAzIECCMQJ1CCH1iCH2C9IGgAcAB4AIABhQKIAYUCkgEDMi0xmAEAoAEBqgEHZ3dzLXdpeg&sclient=psy-ab&ved=0ahUKEwiu8rTb_NHqAhVKmqQKHYH8AKYQ4dUDCAw&uact=5

title: stm8tool is not available for you operating system (ubuntu OS)

Answers: 0


body:
I want to control two hitec hs55 micro servos via a Nodemcu v3. These need at least 4.8 V power supply acc to data sheet.

**Specs:**

Hs-55 micro servo:

Voltage range: 4.8-6 V

Current Drain - no-load (4.8V): 150 mA

Pulse Amplitude: 3-5V

NodeMCU (v3):

From what I found it seems like it can "reliably supply 600 mA".

3.3V pins (standard)

5 V (pin VU), Directly connected from the USB (?)

From what I understand it is generally a good idea to supply power to servos separately, otherwise the board can be damaged. Is this also the case here or would it be OK to connect the supplies to the servos from the VU pin? I'm thinking that there is a possibility it could be ok since it is directly connected to the USB.

For the signals I will use the normal GPIO pins.

Thank you in advance :-)

title: Nodemcu v3 - Power supply via VU pin?

Answers: 2

body:
Supplying the servo from the USB is generally okay, but if it works or not depends on the USB host you use.
The data you mention is not relevant, though:
  - 150mA are valid under no load, when there is a load the servo will sink more current
  - 600mA probably refers to the onboard linear regulator which provides the 3.3V for the ESP. Depending on what the ESP has to do, it may require those 600mA on itsown and the connected circuit.

You can simply try what you suggested, it won't harm the nodeMCU. If it doesn't work the reason is probably the USB host not being able to provide the required current (a fast-charge usb wall charger should work).

body:
The [circuit diagram](https://github.com/nodemcu/nodemcu-devkit-v1.0/blob/master/NODEMCU_DEVKIT_V1.0.PDF) of a NodeMCU shows that there's a [schottky diode](https://en.wikipedia.org/wiki/Schottky_diode) between **Vusb** (the voltage input supplied by USB) and the Vin pin. This has the effect of reducing the approximate 5V voltage supplied by your typical USB jack/outlet/cable to something slightly lower. In my case, the apple USB charger adapter provides 5.1V but this gets reduced to 4.76V on the Vin pin. This Vin voltage is also quite noisy. I don't know if that will affect your servos. I've run one NodeMCU from the Vin pin of another NodeMCU pin without any trouble.

The schottky diode in the NodeMCU is a 1n5819/SS14/S4(SOD_323). I'm not certain, but if [this](https://www.vishay.com/docs/88746/ss12.pdf) is the correct datasheet, it says it can supply 1 amp, which sounds like enough. If I were you, I'd try and see if I could get power directly from the USB source rather than taking it off the NodeMCU pin. It might work off the pin, though. Try and make sure you get a USB that supplies at least 5.1V, though. It's going to be close.

EDIT: I would also add that the NodeMCU will be drawing power, too. If you are drawing 300mA with your servos and 100-150mA with your nodeMCU, that's cutting it pretty close for most USB power sources. A Macbook, for example, can only supply 500mA via a USB port. [This article](https://diyi0t.com/how-to-reduce-the-esp8266-power-consumption/) says a NodeMCU can consume up to 400mA under some circumstances.

Generally speaking, I've been told that it's a bad idea to use GPIO pins to drive anything that draws a significant amount of power. I'm thinking you should maybe consider using some kind of servo driver or relay or something.


body:
I want to avoid soldering for health reasons. I have no well-ventilated open area in my apartment. For a board/modules that have no pins but only holes, how can I connect pins to the holes without soldering?

For certain popular hardware like Raspberry Pi Zero, there seems to be something called "hammer header"

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

but the problem is those have a fixed, pre-determined number of pins, not individual pins. So, if a hardware has 5 holes instead of 20 holes, that thing cannot be used. Is there a hammer header for a single pin? So that if the hardware has 5 holes I would just use 5 of them. I have searched the Internet, but no result. Also, the "hammer header" itself seems to be rare. I could not find a single online store in my country that sells it.

Some existing answer mentioned "Pomona minigrabber", but that thing seems to be temporary. That is, I cannot move the device (it looks that it will fall off). So, that is probably not the answer I want.

A secondary, less-important question, but if I installed hammer pin headers (seems like one has to hit it with an actual hammer to install it), can I un-install (remove) the headers?

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

title: Connecting an arbitrary number of pins to pin holes without soldering?

Answers: 4

body:
As you already have seen, there are not many options to contact such boards without soldering, because **they are meant to be soldered**. Those hammer headers are an option. When you find a seller for your country, it should also have these in different sizes/numbers of pins.

Though contacting the board with the pins is not the only problem, you may face. As long as you are experimenting, the typical breadboard is often enough. But when you want to make something more permanent, reliable, current thirsty or noise sensitive, a breadboard is a bad choice. In that case you would also need to solder. Soldering is just a very integral part of electronics.

---

As others have wrote in the comments, I would also consider soldering as a hobbyist as safe, especially, when you take some precautions. A "well ventilated area" can be a simple room with the window open and a small fan directed to the working place, so that the fumes don't directly go up your nose. That is already a very big improvement, which is also rather cheap. That's also about what the woman does in the video, that you linked. And washing your hands after soldering is also a good measure. (I'm doing soldering the described way for about 15 years now, without any health issues)

In the video, that you linked, they say, that the fumes are toxic and their effect adds up. Letting aside, that they don't back it up with any data and I cannot either, they also don't talk about the amount of solder work, that they consider here. As an electronics beginner you most likely will just solder very rarely for getting pin headers on boards or maybe contacting a motor. The main work most likely will still be done on the breadboard. So here the exposure is so small, that you don't need to consider more than the above safety measures. These will also last rather long, as you get more profound in electronics. And when keeping up that hobby, you maybe wanna invest in a more professional filter system, as you are doing more solder work.

Doing electronics while being that scared of soldering will not be much fun. For the start you might get away by only buying presoldered boards. But very fast you will run against walls with this. Not a good start for a beginner.

But in the end it's your own decision. You have all right to be afraid of solder fumes, though that just might disqualify electronics as a hobby for you.

> if I installed hammer pin headers (seems like one has to hit it with an actual hammer to install it), can I un-install (remove) the headers?

That depends on the pin headers, but most likely no. You would need physical force to get them off. And the pads on a PCB are not very strong. They are made to be soldered, not for tearing the pins off without any damage. But why would you want to remove the headers? You only very rarely solder wires directly to the board for connecting with other parts. Either you solder it onto another PCB (where the pin headers come in handy), or you use a female header on a PCB or a cable for making the connection temporary. For example all my small Arduinos get pin headers soldered to them, so I can put them onto my own PCBs via female headers on the PCB. With that I can also disconnect or replace the Arduino if I need to.

body: Why not get a fume extractor, there are all types, some even have filters. Simply do a google search for "fume extractor", on my first try I got 587,000 hits. The price is all all over the map even for the same model.

body:
I had a problem where a sensor I bought came with holes and the pins not attached. I do not have any soldering skills and searched for a solution. I ended up wrapping tinfoil around each of the small pins to increas their diameter and jamed it in the sensor's holes. As far as I can tell, it is working. It is a bit tidious and is clearly not a long term solution but ended up working at least to test my sensor and set it up.
I couldn't find any solution online without having to buy something else so here you go, if any one is looking for a quick solution with house hold items. Hope it can help any one in need.

(make sure the tinfoil is not in contact with other pins or other metalic part of your sensor as it could cause shorts.... be careful not to damage your devices :) )

body:
I placed the arduino on a breadboard with the pins on the breadboard 1 pinhole further apart than it 'should' be, this way you can press the arduino down and the arduino will fasten itself in place.

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

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


body:
I am pairing an Arduino UNO with a Yost Labs 3-Space Sensor Nano, the user manual for said sensor can be found [here][1] and the user manual for the sensor family [here][2] (kinda confusing, Yost Lab's documentation contradicts itself IMO)

This is my code, pretty straight forward (although this is my first time working with SPI). I am 100% sure the wiring is correct, and I have attached a diagram of my wiring [here][3]. The logic voltage converter I am using is [this][4]

I believe that as per the user manual, this should successfully return 3 floats in 4 bytes each, corresponding to the filtered euler angles of pitch, yaw, and roll. However, all I am reading is bytes full of 0xFF (or 11111111 in binary) which I believe corresponds to null / no command.

Are there any visible errors in my code?

    #include <SPI.h>

    SPISettings settings(6000000, MSBFIRST, SPI_MODE0 ); //variable to hold SPI settings
    //Set Slave Select, MOSI, MISO, CLK
    const int CSN = 10;
    const int SI = 11;
    const int SO = 12;
    const int CLK = 13;

    // Needed to convert the bytes from SPI to float
    union u_types {
       byte b[4];
       float fval;
    } data[3];  // Create 3 unions, one for each euler angle

    void setup() {
     //Set Pin Modes
     pinMode(CSN, OUTPUT);
     pinMode(SI, OUTPUT);
     pinMode(SO, INPUT);
     pinMode(CLK, OUTPUT);
     //Set Slave Select High to Start i.e disable chip
     digitalWrite(CSN, HIGH);
     //Initialize SPI
     SPI.begin();
     //pour a bowl of serial
     Serial.begin(9600);
    }

    //function to transfer commands through SPI
    byte transferByte(byte byteToWrite) {

     byte Result = 0x00;
     digitalWrite(CSN,LOW);
     delay(1);
     Result = SPI.transfer(byteToWrite);
     delay(1);
     digitalWrite(CSN,HIGH);
     return Result;
    }

    //function to swap endian
    void endianSwap(byte temp[4]) {
     byte myTemp = temp[0];
     temp[0] = temp[3];
     temp[3] = myTemp;
     myTemp = temp[1];
     temp[1] = temp[2];
     temp[2] = myTemp;
    }

    void loop() {
     SPI.beginTransaction(settings);

     // Clear the internal data buffer on the IMU
     byte result = transferByte(0x01);
         Serial.print("Cleared internal buffer. Result: "),Serial.println(result);

     // Send start of packet:
     result = transferByte(0xF6);
          Serial.print("Send start of packet. Result: "),Serial.println(result);

     // Send command (tared euler angles)
     result = transferByte(0x01);
          Serial.print("Send commmand 0x01. Result: "),Serial.println(result);

     // Get status of device:
     result = transferByte(0xFF);
          Serial.print("Status of device. Result: "),Serial.println(result);

     while (result != 0x01) {  // Repeat until device is Ready
       delay(1);
       result = transferByte(0xFF);
       Serial.print("Status of device. Result: "),Serial.println(result);
     }

     // Get the 12 bytes of return data from the device:
     for (int ii=0; ii<3; ii++) {
       for (int jj=0; jj<4; jj++) {
         data[ii].b[jj] =  transferByte(0xFF);
         delay(1);
       }
     }

     SPI.endTransaction();

     for( int mm=0; mm<3; mm++) {
       endianSwap(data[mm].b);
     }

     Serial.print("fval 1:"), Serial.println(data[0].fval);
     Serial.print("fval 2:"), Serial.println(data[1].fval);
     Serial.print("fval 3:"), Serial.println(data[2].fval);

     delay(3000);
    }

  [1]: https://yostlabs.com/wp/wp-content/uploads/pdf/3-Space-Sensor-Users-Manual-Nano.pdf
  [2]: https://yostlabs.com/wp/wp-content/uploads/pdf/3-Space-Sensor-Users-Manual-1.pdf
  [3]: https://i.stack.imgur.com/NReZr.png
  [4]: https://www.amazon.ca/gp/product/B07V1YY8FH/ref=ppx_yo_dt_b_asin_image_o00_s00?ie=UTF8&psc=1

title: SPI communications with an Yost Labs IMU

Answers: 1

body:
You almost certainly shouldn't raise CSN after each byte, only after the entire packet.

Although the data sheet is not explicit the chip select is usually used to frame an entire command. As it is at the moment it keeps starting a new transaction.

I like the comment in the data sheet that "...the 3-Space Sensor will not work properly in outer space or on planets with no magnetic field".


body:
I have an Arduino sketch that serves an HTML web page using the standard Ethernet library (https://github.com/arduino-libraries/Ethernet) and the Ethernet Web Server library (https://github.com/khoih-prog/EthernetWebServer). I am serving HTML stored directly in the Arduino memory. The processor is the ARM Cortex M0+. Here is an extract from the code I am using:
```
#include <Ethernet.h>
#include <EthernetWebServer.h>

#define webpage "Big HTML string"

EthernetWebServer webServer;
void setup()
{
  SerialUSB.begin(9600);

  Ethernet.begin(settings.macAddress, settings.ipAddress, settings.ipAddressDns, settings.ipAddressGateway, settings.ipAddressSubnet); // 'settings' is a struct declared elsewhere
  webServer = EthernetWebServer(settings.portHttp);

  webServer.on("/login", [&webServer]{ // /login handler
    webServer.send(200, "text/html", webpage);
  });
}

void loop()
{
  webServer.handleClient();
}
```

When I refresh the page (send GET request) more than 9 times or so the Arduino freezes. I have checked by placing SerialUSB.println() inside the code and it seems to stop before even entering the "/login handler" callback.

Does anyone know the cause or at least how to solve this?

title: Arduino blocks when serving web pages

Answers: 0


body:
I am running the blinking LED program with stm32duino, and an STM32.  By trial and error, and a bit of debugging, I have worked out the following:

* pin C13 blinks as well as the built in LED
(except my external LED is on the built-in LED is off)
* the constant `LED_BUILTIN` equals 17

I found this pinout: https://stm32duinoforum.com/forum/wordpress/wp-content/uploads/2016/07/The-Generic-STM32F103-Pinout-Diagram.pdf

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

But it says nothing about C13 being pin 17.

Does anybody know where to look to find out where the arduino pins line up to the codes on the board?

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

title: pinout for stm32duino with bluepill

Answers: 1

body:
OK if this helps anybody, they give you constants for every pin that look like `PC14` for the one that says `C14`, so you don't need to worry about the integers that they assign to the pins.

I mean there are constants named for the yellow boxes on the above diagram.


body:
I was trying to find out how this library can run multiple stepper motors at the same time, and I saw this important function called...

    void AccelStepper::setOutputPins(uint8_t mask)
    {
        uint8_t numpins = 2;
        if (_interface == FULL4WIRE || _interface == HALF4WIRE)
     numpins = 4;
        else if (_interface == FULL3WIRE || _interface == HALF3WIRE)
     numpins = 3;
        uint8_t i;
        for (i = 0; i < numpins; i++)
     digitalWrite(_pin[i], (mask & (1 << i)) ? (HIGH ^ _pinInverted[i]) : (LOW ^ _pinInverted[i]));
    }

why is it using `uint8_t`? and what is a `mask`? and Is this line:

 digitalWrite(_pin[i], (mask & (1 << i)) ? (HIGH ^ _pinInverted[i]) : (LOW ^ _pinInverted[i]));
sending a step signal to multiple stepper?

title: AccelStepper library advanced codes!

Answers: 1

body:
The `setOutputPins()` function sets the pins for a pulse for a single stepper. Depending on the used stepper motor a different number of pins has to be set (normal stepper drivers have 2 pins, the ULN2003 and its siblings have 4) in a different way. For that the function first determines the number of pins to use via the `_interface` member variable of the class.

The `mask` parameter contains the states of the pins. Each bit represents one pin. If the corresponding bit is set to 1, the pin will be set to an active state. If not, it will be set to an inactive state. Normally an active state (like I have called it here) is HIGH, an inactive state is LOW. But when working with different stepper drivers, some pins might work with an inverted logic. Thus the value (LOW or HIGH) is inverted, if the pin is marked as inverted in the `_pinInverted` array. This logic is in the line

    digitalWrite(_pin[i], (mask & (1 << i)) ? (HIGH ^ _pinInverted[i]) : (LOW ^ _pinInverted[i]));

The idiom `condition ? expression : expression` represents an embedded if condition. If the condition evaluates to `true`, the first expression is used, else the second expression. With `mask & (1 << i)` we are checking, if the `i`th bit in `mask` is set. If yes, we use the next expression: `HIGH ^ _pinInverted[i]`. Here the `^` bitwise XOR operator is used to invert the value, if `_pinInverted[i]` is set to 1 (and thus marked the pin as inverted). If `_pinInverted[i]` is zero, the value will stay as it is. The handling of the LOW value is similar.

For understanding that better, you might want to read more about bitwise operators, if you haven't already done so.

> why is it [the `mask` parameter] using `uint8_t`?

`uint8_t` is the smallest type, that could be used: 1 byte. As each bit represents one pin, and the library supports steppers with up to 4 pins, only 4 bits are needed at max. Thus using the smallest type with 8 bits is sufficient.

> Is this line sending a step signal to multiple stepper?

No, it is setting the pins of a single stepper motor. Each instance of the `AccelStepper` class represents a single stepper motor. Thus every function in it also only talks to one single motor. You haven't really explained, how you want to add the feedback functionality. But you should not change the `AccelStepper` class to handle multiple motors. That does not make sense to me. Each motor has to be controlled individually and this class is there to capsule the work behind that. Thats the idea behind making a class for this.

I guess you want to drive multiple motors, each with it's own feedback loop. So then you first need to change the `AccelStepper` class for supporting that feedback loop. How this is done depends very much on your type of feedback loop. Also the `setOutputPins()` method is not a good place for that. It is a very low level function. You need to start further up in the call chain, maybe in the `step()` method or the `runSpeed()` method (this really depends on how you want to handle the feedback). Also you need to write methods to set up and handle the encoders input. You may need to configure timers and/or interrupts for reading them correctly.

For then supporting multiple stepper motors, you could still look into the `MultiStepper` class. You could change it to fit with your changes in `AccelStepper` or write your own wrapping class. That mostly depends on how you want the multiple steppers to behave.


body:
**Problem:** I need to send small integer numbers (single-digit numbers suffices) between two arduinos located approximately 50-60m away from each other.

The connection must be made through cables. I have read that the mentioned distance is too long for using serial communication. I do not care if the method is not fast, delays up to one or two seconds are ok for this. If it helps: the devices (Arduino UNO or similar) will run not  yet written codes for a simple alarm system (with no cameras/images).

---

**Question:** What is a good way to this?

---
**My efforts:** I thought a couple of alternatives to solve this problem. Both involve the use of PWM signals sent from a device *A* to another *B*.

 - One of them requires some DAC in *A*  and read the analog input in *B*. The values read are then mapped to the small integer lists. I found some disadvantages with this approach:
   - Increment of hardware complexity and cost. Although I have read that the digital to analog conversion can be made with cheap capacitors I would have many problems to acquire them because of the lock-down of my country.
   - Probably I will need to  do many test to set up the mapping procedure  due to voltage drop.
- The second is just read the *digital* input in *B* many times during a fixed period (e.g. 0.1 or 1 second) and average the values that were read in that period. My bet is that the devices are not synchronized and then the average (times 1023) in such longs periods would be close to the *value* sent by analogWrite(somepin, *value*). Finally, the accepted value would be the closest value in alist of acceptable values.
***Example***: For passing one of the numbers 0,1,2 or 3 the *A* device will output 0, 341, 682 or 1023, respectively. Eg. for passing "1" *A* will do **analogWrite(somepinA, 341)**. *B* will read **int lecture = digitalRead(somepinB)** and get the time average of *lecture* for some time period. After multiplication by 1023 it could return something like "312". Then, it must find the value in [0, 341, 682,1023] closest to 280 (341) and map to 1.
   - Even if they were synchronized some way, I think that I could send 0 or 1 using random numbers or digitalWrite(somepinA) (Is it possible? Advantages? Disadvantages?)
---
I'm a novice in this field so I do not known if there is something wrong with my approach. I would also appreciate if a better alternative is proposed.

Thanks in advance.

title: Sending minimal data between two Arduinos far away from each other

Answers: 2

body:
**RS-485 is best (you can buy some modules for this from Adafruit, Amazon, eBay, etc)**, but you can use the built-in hardware RS-232 serial UARTs from each on pins 0 and 1 so long as the baud rate is really really low. The lower the baud rate, the longer the range can be because lower baud rates reject noise better (and the longer the cable, the worse the noise, since the longer the cable the more it acts like an antenna and an inductor and a capacitor). Here are some rough estimates of how far you can transfer regular-logic-level unbalanced RS-232 signals:

[![enter image description here][1]][1]
Source:
https://www.tldp.org/HOWTO/Remote-Serial-Console-HOWTO/serial-distance.html

If this trend continues, you should be able to get like 120m at 1200 bps (baud), 240m at 600 bps, 480m at 300 bps, etc. maybe even up to > 1000m at 50 bps. I don't think the trend will continue like that, and we are using 5V TTL logic (signal voltage) levels here instead of RS-232's +/- 12V or so, so our logic levels are much worse and will have less range, so just use `50` baud and give it a shot:

    // do on each Arduino
    Serial.begin(50); // 50 baud = 10 bytes/sec throughput rate; see below

Note that for [8-N-1 serial communication baud rate](https://en.wikipedia.org/wiki/8-N-1), which is the default on Arduino, there are **10 bits** per byte sent over the wire. This is because there is "one start bit, the eight data bits, and the one stop bit" for every 8-bit byte sent. That's an effective throughput data rate of 80%. This means a baud rate of 50 bps (bits per second) only can transmit 50/10 = _5 bytes per second_. That's it! That's suuuuuper slow, but if it's fast enough for your application, it's fast enough!

I hypothesize 5V TTL twisted quad RS-232 communication between two Arduinos would have a maximum range at `50` baud of about 1000m/(24V span for regular RS-232 / 5V span for 5V TTL logic RS-232) = **208m**. Just a crude guestimate. Please report back any findings you get from your experiments. I'd like to hear about it.

Assuming that this all *does* work, it would also be useful to start increasing the baud rate on each device until the data starts getting corrupted. Back off on the baud rate a little, and that's your maximum baud rate. Take that maximum baud rate and divide by 2 or 3, and that's your maximum "safe" baud rate perhaps. If you need throughput that is as high as possible, then that's what I'd do. Ex: maybe in your case `50` baud works just fine, so you increase it. At `1000` baud you start seeing corrupted data, so you back off to `800`. At that point you no longer see corrupted data. So, divide that by 2 or 3 and you get a maximum "safe" baud for your setup of perhaps 800/3 = `267` to 800/2 = `400`.

Try using a _twisted quad_ cable (wires are twisted together in groups of 4) to reduce noise and increase range, and set the baud rates on each Arduino to like `50`. You will need 3 wires connected between the Arduinos:

1. GND to GND
1. Tx to Rx
1. Rx to Tx

Power them each separately with ungrounded power supplies.

Communicate via `Serial.write()` and `Serial.read()` (so long as `Serial.available()` shows some data is available in the read buffer).

# More on balanced vs unbalanced lines, and why I recommend "twisted quad" wire:

Normally, RS-232 is considered to be an [unbalanced line](https://en.wikipedia.org/wiki/Unbalanced_line) transimission system. This means the impedance in the transmission wire is not equal to the impedance in the return wire, which would be a common ground between the sender and receiver, in conjunction with (in parallel with) an Earth ground through the building wiring and/or actually through the Earth...literally, the dirt you walk on. By powering each Arduino with an *ungrounded* power supply, such as a 2-prong power supply, however, which is common, there is no Earth ground connected to the Arduino. Furthermore, by only having a single transmission line active at any moment between two Arduinos, you have just balanced the transmission between them. Now, the out path is a single Tx signal from one Arduino to the other, and the return path has matching impedance, as it is your single, common GND wire between the two Arduinos. You now have [balanced line](https://en.wikipedia.org/wiki/Balanced_line) RS-232 TTL logic level transmission between the two Arduinos. Balanced line transmission can have improved noise rejection and range by using a twisted pair between the two lines. In this case, however, there are 3 lines: Tx --> Rx, Rx --> Tx, and Gnd --> Gnd. So, you should use **twisted quad** wire, which means 4 wires at once are twisted together. Connect all 3 lines to the same twisted quad bundle. Again, remember, this assumes only one Arduino is transmitting at a time on one single wire in one single direction at a time (so as to not negate your return current through the GND line when transmitting on two lines, one in each direction, or double your return current through the GND line when transmitting on two lines each in the same direction [assuming you had multiple UARTS on each device]), thereby this usage creates a balanced line system since they also aren't truly grounded through a 3-prong grounded power supply. If these 2 requirements are met (1 Arduino transmits at a time, and at least one of them is not grounded to the building wiring), use twisted quad wire, as the system is balanced line communication. If it is not the case, because you are transmitting from each Arduino to the other at exactly the same time, or because *both* (not one) Arduinos are grounded to the building, thereby offering an alternative return path through the building ground wiring, then twisted quad cable will not benefit you, and you should use regular untwisted wiring.

Having said all that, experimentation is the real boss here. Try it out. if I didn't have twisted quad wire I'd try twisted pair, and if I didn't have twisted pair, I'd try untwisted wire.

# Regarding your approach about using PWM to produce an analog output to be read by the receiving end:
Using PWM to produce an analog voltage to be read by the receiving end is an interesting approach. Without filtering, I think what you'd be doing is producing tremendous noise, however, literally producing electromagnetic radiation (think like low frequency radio or TV waves or something), where this huge 60m wire is your broadcasting antenna. If you put a 20k~50k resistor right at the sending end, however, and a 1uF capacitor right at the receiving end, however, to filter this PWM into an analog output immediately at the sending end, I think it would then eliminate your antenna effect where you are broadcasting something, and work much better, but still be highly susceptible to external noise influencing it. Give it a shot, but I suspect a simple set of digital pins to set HIGH or LOW on different pins to match different states would be much much much better than any analog signal at those lengths, with a 50 baud serial signal being the next best for signal-to-noise thereafter.

**So, in order of best to worst [signal-to-noise ratio (SNR)](https://en.wikipedia.org/wiki/Signal-to-noise_ratio):**

1. differential pair (referenced to each other) digital HIGH/LOW values to represent states, which you update *very slowly*
1. RS-485 differential pair serial transmission
1. _Note: for all of the following really low-speed digital signal sending scenarios, you might try it with the low-pass filter **shown in the schematic below** too, as it may help reject noise._
1. single-ended (referenced to GND) digital HIGH/LOW values to represent states, which you update *very slowly*
1. super low-speed SPI (including bit-banging it); ie: declare any digital pin a `CLOCK_PIN`, and any other digital pin a `DATA_PIN`. Set a clock pin LOW, set a data pin HIGH, set the clock pin HIGH. The clock transition tells the receiver (you have to code this up) to read the data pin, so you just read a `1` bit. Set the data pin LOW, set the clock pin LOW. The clock transition tells the receiver to read the data pin, so you just read a `0` bit. Leave the data pin low, set the clock pin HIGH again. You just sent another `0` bit, etc etc. Send data like this really slowly. It will work at great lengths--even better than asynchronous serial since it's synchronous.
1. asynchronous serial (+/- 12V true RS-232) at 100 baud
1. asynchronous serial (+/- 12V true RS-232) at 50 baud
1. asynchronous serial (5V TTL RS-232) at 50 baud
1. asynchronous serial (3V TTL RS-232) at 50 baud
1. analog value filtered with resistor and capacitor low-pass RC filter; update: I'd try this filtering layout for sending analog values via PWM (**see schematic below**, but use the higher resistor value I describe in my bullets underneath the schematic, rather than the lower value I show in the schematic); the filter may also be beneficial to help filter noise when doing low-speed _digital_ communication too, so give it a shot in your 50-baud rate serial setup above too:
    1. Send with `analogWrite()` (PWM); receive with `analogRead()`.
    1. Report back on this too please. I'm very curious if it would work.
1. unfiltered PWM---square wave antenna broadcasting who knows what--could result in an interesting broadcasting system for you. Add a transistor and you could really amp up the power and broadcast some interesting signals out! Get some good high power going here (1W~10W+) and maybe even get the government to find out who's jamming GPS and cellular? I don't know: could be interesting!

**Schematic of low-pass RC filter to reduce noise between the two Arduinos when sending really low-speed digital signals (better), or slowly-changing analog signals (worse) between the two sides:**

![schematic](https://i.stack.imgur.com/RDR5C.png)

1. **For filtering the digital signals (ex: 5V TTL pseudo-RS232 serial at 50 to 100 baud)**:
    1. Use 470 Ohms for each resistor, as shown above.
    1. This results in a **cutoff freq** of 847 Hz, so stay below ~169 baud (`cutoff_freq/5 = 847Hz/5 = 169` or so) for digital signal sending through this filter.
1. **For filtering analog signals sent via `analogWrite()`**:
    1. [Since most Arduino pins have a PWM Frequency of 490 Hz][2], we need a cutoff frequency of ~490Hz/10 = 49Hz _or lower_ to cleanly filter out the PWM frequency and result in a true analog output.
    1. Using the calculator linked-to below, that means you should use R values of at least **10k each**, which results in a **cutoff freq.** of 40 Hz. You can use **20k** resistors each too, for a cutoff freq. of about 20 Hz.
1. To _increase_ cutoff frequency to allow _higher_ baud rates, _decrease_ either R or C or both.
1. For a cutoff frequency calculator, see: https://electronicbase.net/low-pass-filter-calculator/#rc-low-pass-calculator --> "RC Low Pass Filter Calculator" --> enter, for example, 940 Ohms (470 x 2) as the resistor value and 0.2uF (0.1uF x 2) as the capacitor value to see that the resulting cutoff frequency for this low-pass filter is 846.57 Hz.

I'm no filter expert, but this is what I'd try. If someone sees some glaring errors in this filter or ways to improve it, please comment below the answer.

# Extras:
Here's the Bode plot for the above series filter I show except with a 1k resistor and 0.1uF (100nF) capacitor followed by the same thing again. The purple line is the voltage we care about. Source: [godfreyl, here.][3]

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

The cutoff frequency here is 398Hz, which is where the -3db drop occurs, which corresponds to the half power and 70.7% voltage attenuation point. (`sqrt(0.50) = 0.707`, so `0.707^2 = 0.5`)). You can read more about [cutoff frequency here][5].

[![enter image description here][6]][6]

# Additional reading:
1. https://www.tldp.org/HOWTO/Remote-Serial-Console-HOWTO/serial-distance.html
1. [Google search for "is rs232 balanced?"](https://www.google.com/search?q=is+rs232+balanced?&oq=is+rs232+balanced?&aqs=chrome..69i57.3961j0j7&sourceid=chrome&ie=UTF-8)
1. https://www.idc-online.com/technical_references/pdfs/data_communications/tutorial_2.pdf
1. http://www.iec-usa.com/Browse05/DTBALUN.html
1. https://en.wikipedia.org/wiki/Signal-to-noise_ratio

  [1]: https://i.stack.imgur.com/hoykI.png
  [2]: https://www.arduino.cc/reference/en/language/functions/analog-io/analogwrite/
  [3]: https://www.edaboard.com/threads/low-pass-filters-in-series-does-it-work.306890/#post-1313561
  [4]: https://i.stack.imgur.com/Q10nU.png
  [5]: https://en.wikipedia.org/wiki/Cutoff_frequency
  [6]: https://i.stack.imgur.com/6TGwp.png

body:
It appears the easiest would be to use a simple CAN transceiver on each end, one set to transmit and the other to receive. You did not mention bidirectional communications although both Physical layers suggested below will support that quite easily. The electrical characteristics of the CAN bus cable restrict the cable length according to the selected bit rate. You can use cabling up to 250 meters with the baud rate of 250 kbit/s. The maximum bus length with a bit rate of 10 kbit/s is 1 km, and the shortest with 1 Mbit/s is 40 meters.
Another approach would be to used RS485. RS485 is popular for inexpensive local networks, multidrop communication links and long haul data transfer over distances of up to 4,000 feet. The use of a balanced line means RS485 has excellent noise rejection and is ideal for industrial and commercial applications. Note these typically are driven with Async signals from a uart or similar device. Software serial would work great and leave the onboard serial port for debugging. the Async communications does the syncing automatically, nothing for you to do, just keep the baud rates the same.


body:
with this sketch i can independently control 4 dc motors cw, ccw, and rotating each of them until the hall sensor related to it detects an magnetic field. what im trying to do now is to create a mode of operation in wich:just pressing button "nine", and first motor starts rotating until its hall sensor detects a magnetic field, after five seconds, the second motor acts the same and so on, ather the fourth motor, after 5 seconds, the first motor starts again. i spent like 5 hours trying but still cant do it. maybe for a pro its not that big deal cose its my first serious Arduino project.
```
#include <TLE94112.h>
#include <Tle94112Motor.h>
#include <IRremote.h>

#define unu 0x1
#define doi 0x2
#define trei 0x3
#define patru 0x4
#define sound 0x55
#define picture 0x54
#define feature 0x50
#define install 0x52
#define cinci 0x5
#define sase 0x6
#define sapte 0x7
#define opt 0x8
#define tv 0x63
#define av 0x56
#define e 0x60
#define eo 0x42

int RECV_PIN = 2;
int hallSensorPin1 = 3;
int hallSensorPin2 = 4;
int hallSensorPin3 = 5;
int hallSensorPin4 = 6;
int state1;
int oldState1 = 1;
int runMode1 = 0;
int state2;
int oldState2 = 1;
int runMode2 = 0;
int state3;
int oldState3 = 1;
int runMode3 = 0;
int state4;
int oldState4 = 1;
int runMode4 = 0;

Tle94112 controller = Tle94112();
Tle94112Motor motor1(controller);
Tle94112Motor motor2(controller);
Tle94112Motor motor3(controller);
Tle94112Motor motor4(controller);

IRrecv irrecv(RECV_PIN);
decode_results results;

void setup()
{ irrecv.enableIRIn();
  controller.begin();

  motor1.connect(motor1.HIGHSIDE, controller.TLE_HB1);
  motor1.connect(motor1.LOWSIDE, controller.TLE_HB2);
  motor1.setPwm(motor1.HIGHSIDE, controller.TLE_PWM2);
  motor1.setPwmFreq(motor1.HIGHSIDE, controller.TLE_FREQ200HZ);

  motor2.connect(motor2.LOWSIDE, controller.TLE_HB3);
  motor2.connect(motor2.HIGHSIDE, controller.TLE_HB4);
  motor2.setPwm(motor2.HIGHSIDE, controller.TLE_PWM2);
  motor2.setPwmFreq(motor2.HIGHSIDE, controller.TLE_FREQ200HZ);

  motor3.connect(motor3.HIGHSIDE, controller.TLE_HB5);
  motor3.connect(motor3.LOWSIDE, controller.TLE_HB6);
  motor3.setPwm(motor3.HIGHSIDE, controller.TLE_PWM2);
  motor3.setPwmFreq(motor3.HIGHSIDE, controller.TLE_FREQ200HZ);

  motor4.connect(motor4.LOWSIDE, controller.TLE_HB7);
  motor4.connect(motor4.HIGHSIDE, controller.TLE_HB8);
  motor4.setPwm(motor4.HIGHSIDE, controller.TLE_PWM2);
  motor4.setPwmFreq(motor4.HIGHSIDE, controller.TLE_FREQ200HZ);

  motor1.begin();
  motor2.begin();
  motor3.begin();
  motor4.begin();
}
void loop()
{
  if (irrecv.decode(&results)) {
    Serial.println(results.value, HEX);
    irrecv.resume();

    if (results.value == unu || results.value == 0x801 || results.value == 0x2049) {
      motor1.start(63);
      runMode1 = 0;
    }
    if (results.value == cinci || results.value == 0x805 || results.value == 0x2053) {
      motor1.start(-63);
      runMode1 = 0;
    }
    if (results.value == tv || results.value == 0x63 || results.value == 0x2111 || results.value == 0x83F || results.value == 0x3F) {
      motor1.coast();
      runMode1 = 0;
    }
    if (results.value == sound || results.value == 0x55 || results.value == 0x2103 || results.value == 0x837 || results.value == 0x37) {
      motor1.start(63);
      runMode1 = 1;
    }
    if (results.value == doi || results.value == 0x802 || results.value == 0x2050) {
      motor2.start(63);
      runMode2 = 0;
    }
    if (results.value == sase || results.value == 0x806 || results.value == 0x2054) {
      motor2.start(-63);
      runMode2 = 0;
    }
    if (results.value == av || results.value == 0x56 || results.value == 0x2104 || results.value == 0x838 || results.value == 0x38) {
      motor2.coast();
      runMode2 = 0;
    }
    if (results.value == picture || results.value == 0x54 || results.value == 0x2102 || results.value == 0x836 || results.value == 0x36) {
      motor2.start(63);
      runMode2 = 1;
    }
    if (results.value == trei || results.value == 0x803 || results.value == 0x2051) {
      motor3.start(63);
      runMode3 = 0;
    }
    if (results.value == sapte || results.value == 0x807 || results.value == 0x2055) {
      motor3.start(-63);
      runMode3 = 0;
    }
    if (results.value == e || results.value == 0x60 || results.value == 0x2108 || results.value == 0x83C || results.value == 0x3C) {
      motor3.coast();
      runMode3 = 0;
    }
   if(results.value==feature||results.value==0x50||results.value==0x2098||results.value==0x832||results.value==0x32){
      motor3.start(63);
      runMode3 = 1;
    }
    if (results.value == patru || results.value == 0x804 || results.value == 0x2052) {
      motor4.start(63);
      runMode4 = 0;
    }
    if (results.value == opt || results.value == 0x808 || results.value == 0x2056) {
      motor4.start(-63);
      runMode4 = 0;
    }
    if (results.value == eo || results.value == 0x42 || results.value == 0x2090 || results.value == 0x82A || results.value == 0x2A) {
      motor4.coast();
      runMode4 = 0;
    }
    if (results.value == install || results.value == 0x52 || results.value == 0x2100 || results.value == 0x834 || results.value == 0x34) {
      motor4.start(63);
      runMode4 = 1;
    }
  }
  state1 = digitalRead(hallSensorPin1);

  if (state1 == HIGH) {
    oldState1 = 1;
  }
  if (state1 == LOW && oldState1 == 1 && runMode1 == 1) {
    motor1.coast();
    oldState1 = 0;
  }
state2 = digitalRead(hallSensorPin2);

  if (state2 == HIGH) {
    oldState2 = 1;
  }
  if (state2 == LOW && oldState2 == 1 && runMode2 == 1) {
    motor2.coast();
    oldState2 = 0;
  }

  state3 = digitalRead(hallSensorPin3);

  if (state3 == HIGH) {
    oldState3 = 1;
  }
  if (state3 == LOW && oldState3 == 1 && runMode3 == 1) {
    motor3.coast();
    oldState3 = 0;
  }
  state4 = digitalRead(hallSensorPin4);

  if (state4 == HIGH) {
    oldState4 = 1;
  }
  if (state4 == LOW && oldState4 == 1 && runMode4 == 1) {
    motor4.coast();
    oldState4 = 0;
  }
}
```

title: multiple working modes for motors

Answers: 0