body:
i found following code online, to read the value of a touch sensor... i am having difficulties understanding how the 2 second timeout on the marked line works..
` if ((touch_sensor_value (TOUCH_timeSeconds * 1000))) {`

`touch_sensor_value` is the value read from the touch input.. and the rest?? i dont see any comparison with anything in the parenthesis, i cant figure out how this if condition is working...

    #define TOUCH_timeSeconds 2
    uint64_t now = millis();
    unsigned long lastTrigger_TOUCH = 0;
    bool startTimer_TOUCH = false;
    bool buttonIsPressed = false;

    int touch_sensor_value = 0;
    //Mux control pins
    int s0 = 26;
    int s1 = 27;
    int s2 = 14;
    int s3 = 12;
    //State array
    int currentState ;
    //Mux in “SIG” pin
    int SIG_pin = 33; //is touch sensor
    void setup()
    {
    pinMode(s0, OUTPUT);
    pinMode(s1, OUTPUT);
    pinMode(s2, OUTPUT);
    pinMode(s3, OUTPUT);

    digitalWrite(s0, LOW);
    digitalWrite(s1, LOW);
    digitalWrite(s2, LOW);
    digitalWrite(s3, LOW);

    Serial.begin(115200);
    Serial.println(“Multiplexing 1 Touch sensor ESP32 using CD7HC4067 MUX”);

    }

    void loop() {

    for (int i = 0; i < 16; i ++) {
    currentState = readMux(i);
    touch_sensor_value = touchRead(T9);

    if ((touch_sensor_value (TOUCH_timeSeconds * 1000))) {    <-----!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
    Serial.println(“2 Second LOCK OUT: No rapidly repeating readings”);
    buttonIsPressed = false;
    startTimer_TOUCH = false;
    return;
    }

    //

    }

    // delay(1000);
    }

    int readMux(int channel) {
    int controlPin[] = {s0, s1, s2, s3};

    int muxChannel[16][4] = {
    {0, 0, 0, 0}, //channel 0
    {1, 0, 0, 0}, //channel 1
    {0, 1, 0, 0}, //channel 2
    {1, 1, 0, 0}, //channel 3
    {0, 0, 1, 0}, //channel 4
    {1, 0, 1, 0}, //channel 5
    {0, 1, 1, 0}, //channel 6
    {1, 1, 1, 0}, //channel 7
    {0, 0, 0, 1}, //channel 8
    {1, 0, 0, 1}, //channel 9
    {0, 1, 0, 1}, //channel 10
    {1, 1, 0, 1}, //channel 11
    {0, 0, 1, 1}, //channel 12
    {1, 0, 1, 1}, //channel 13
    {0, 1, 1, 1}, //channel 14
    {1, 1, 1, 1} //channel 15
    };

    //loop through the 4 sig
    for (int i = 0; i < 4; i ++) {
    digitalWrite(controlPin[i], muxChannel[channel][i]);
    }

    //read the value at the SIG pin
    int val = analogRead(SIG_pin);

    //return the value
    return val;
    }

title: Explanation of code found online

Answers: 1

body:
The comment form of a blog is not an appropriate place to publish source
code, as the content-management system (Wordpress here) quite often does
some destructive transformations. For example, here:

```c++
Serial.println(“2 Second LOCK OUT: No rapidly repeating readings”);
```

Wordpress tried to be “helpful” and replaced the ASCII quotes (") with
typographic quotes (“ and ”), which makes the line non-compilable.

As for the line you are asking about:

```c++
if ((touch_sensor_value  (TOUCH_timeSeconds * 1000)))
```

it is likely missing a less-than sign (<), as those are often stripped
from user-generated content for security reasons. I don't know why some
of those signs went through the filter, maybe it has something to do
with the white space surrounding them, but this is pure guess.

Given that the code has been destructively mangled, your options are
either to guess from the context, or post a comment asking for
clarification.


body:
in my arduino project I use the Adafruit CCS811 Air Quality Sensor Breakout - VOC and eCO2, I need the references and sizes of these components, knowing that I have found the electrical diagram but the values and references are not clear as you see in the photo.
Link to the sensor: https://learn.adafruit.com/adafruit-ccs811-air-quality-sensor/overview
Thank you in advance for your help.[![enter image description here][1]][1]

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

title: Adafruit CCS811 Air Quality Sensor

Answers: 0


body:
One thing that always confused me was why we use int or other commands to set the variables to have pin numbers as if those commands were always restricted to pin numbers only. For example

    int ledPin = 13;

Does putting a random number in place of 13 that isn't a pin number cause an error? Right now I haven't checked yet.

I've only begun to realize that if you want to use variables in relation to pins or push buttons you have to set values first and then do associated functions like digitalRead. The commands like int are not like in other programming languages where you can set any values and do mathematical computations. I know it might seem obvious to someone who is used to Arduino, but this perspective is something that helped me grasp things better. Before that, I totally could not understand how things worked because of being confused with how int or other similar variables worked.

title: Does setting a value always mean setting a Arduino pin?

Answers: 1

body:
Note that this is just a C/C++ integer declaration, assigning a value to a variable, like any variable (irrelevant if it is for pin numbers).

You don't have to use a variable, there are similar variations:

**Variable**

    int pinNumber = 13;

in `begin`:

    pinMode(pinNumber, OUTPUT);
    digitalWrite(pinNumber, HIGH);

**Const**

Preferably I like to use a const:

    const int PIN_NUMBER = 13;

Or even better, since it always is a low value:

    const uint8_t PIN_NUMBER = 13;

And use it with capitals.

    pinMode(PIN_NUMBER, OUTPUT);
    digitalWrite(PIN_NUMBER, HIGH);

**#define**

    #define PIN_NUMBER 13

    pinMode(PIN_NUMBER, OUTPUT);
    digitalWrite(PIN_NUMBER, HIGH);

The reason variables are used, is that when you want to use another pin number, you only need to change it in one place, making the sketch better maintainable/adaptable.

I don't know what happens when you give an illegal number (you can try it out yourself).


body:
I've mounted an Ethernet Shield on top of an Arduino UNO. The Arduino is connected via usb to my pc and to the network via ethernet through a switch.
I'm running a simplified verison of the WebServer example and the function to Ethernet.begin() always returns EthernetNoHardware.

I've tried different setups changing the ethernet cables and connecting directly to the router. I also tried adding specific ip, gateway and subnet parameters to Ethernet.begin() however the output doesn't change and the server can't be reached:

```
#include <SPI.h>
#include <Ethernet.h>

byte mac[] = { 0x90, 0xA2, 0xDA, 0x0F, 0xCC, 0x1E }; //mac address on the sticker
IPAddress ip(192, 168, 1, 134);
IPAddress gateway(192,168,1,1);
IPAddress subnet(255,255,255,0);
IPAddress DNSserver(192,168,1,1);
EthernetServer server(80);

void setup() {
  Ethernet.init(10);
  Serial.begin(9600);
  while (!Serial) {
    ;
  }

  Ethernet.begin(mac, ip, gateway, subnet);

  if (Ethernet.hardwareStatus() == EthernetNoHardware) {
    Serial.println("Ethernet shield not found.");
  }

  server.begin();
  Serial.print("server is at ");
  Serial.println(Ethernet.localIP());
}
```

output:

```lang-none
Ethernet shield not found.
server is at 192.168.1.134
```

Any idea on what the issue might be?

title: Ethernet Shield not connecting

Answers: 1

body:
In your sketch DNS IP parameter is missing in `Ethernet.begin`.

It should be `Ethernet.begin(mac, ip, dns, gateway, subnet);`


body:
I have tested this code on Lolin Nodemcu v3 and it is working perfectly. However when I switched to ESP-01 The Wifimanager works but no custom parameters are saved although WIFI Credentials are saved.

<!-- begin snippet: js hide: false console: true babel: false -->

<!-- language: lang-js -->

    #include <FS.h>          // this needs to be first, or it all crashes and burns...
    #include <WiFiManager.h> // https://github.com/tzapu/WiFiManager
    #include <ArduinoJson.h> // https://github.com/bblanchon/ArduinoJson
    #include <ESP8266WiFi.h>
    #include <ESP8266WebServer.h>
    #include <DNSServer.h>

    int ledPin = 2;
    char mqtt_username[40]; char mqtt_password[40];     String mqttusername;    String mqttpassword;

    WiFiManager wm;

    bool shouldSaveConfig = false;
    void saveConfigCallback () {  Serial.println("Should save config");  shouldSaveConfig = true; }

    void setup() {
      Serial.begin(115200);  pinMode(ledPin, OUTPUT);  digitalWrite(ledPin, LOW);

      setupSpiffs();  wm.setSaveConfigCallback(saveConfigCallback);
      WiFiManagerParameter custom_mqtt_username("username", "username", mqtt_username, 40);
      WiFiManagerParameter custom_mqtt_password("password", "password", mqtt_password, 40);

      wm.addParameter(&custom_mqtt_username);  wm.addParameter(&custom_mqtt_password);

      strcpy(mqtt_username, custom_mqtt_username.getValue());     mqttusername = custom_mqtt_username.getValue();
      strcpy(mqtt_password, custom_mqtt_password.getValue());     mqttpassword = custom_mqtt_password.getValue();

      if (shouldSaveConfig) {    Serial.println("saving config");        DynamicJsonDocument doc(1024);
        doc["mqtt_username"] = mqtt_username;    doc["mqtt_password"] = mqtt_password;
        File configFile = SPIFFS.open("/config.json", "w");
        if (!configFile) {  Serial.println("failed to open config file for writing"); }
        serializeJson(doc, Serial);    serializeJson(doc, configFile);    configFile.close();    Serial.println("");    //end save
      }
      while (WiFi.status() != WL_CONNECTED) { delay(100); Serial.print(".");  resetbtn(); }  Serial.println("");
      Serial.print("Connected to WiFi: ");  Serial.println(WiFi.SSID());
      Serial.print("IP: ");  Serial.println(WiFi.localIP());
      Serial.println("connected...yeey :)");
    }

    void loop() {
    Serial.println("user is: ");   Serial.println(mqtt_username);
    Serial.println("pass is: ");   Serial.println(mqtt_password);
    }

    void setupSpiffs(){
    //   SPIFFS.format();
      Serial.println("mounting FS...");

      if (SPIFFS.begin()) {    Serial.println("** Mounting file system **");
        if (SPIFFS.exists("/config.json")) {      Serial.println("** Reading config file **");      File configFile = SPIFFS.open("/config.json", "r");
          if (configFile) {
            size_t size = configFile.size();        std::unique_ptr<char[]> buf(new char[size]);
            configFile.readBytes(buf.get(), size);        DynamicJsonDocument doc(1024);        DeserializationError error = deserializeJson(doc, buf.get());
            if (error) {          Serial.print(F("deserializeJson() failed: "));          Serial.println(error.c_str());          return;        }
            strcpy(mqtt_username, doc["mqtt_username"]);             strcpy(mqtt_password, doc["mqtt_password"]);
          } else {        Serial.println("** Failed to load json config **");      }
          configFile.close();      Serial.println("** Closed file **");
        }
      } else {    Serial.println("** Failed to mount FS **");  }
    }

    void resetbtn() {    if ( digitalRead(ledPin) == HIGH ) {  wm.startConfigPortal("Burooq");    Serial.println("connected...yeey :)");  }   }

<!-- end snippet -->

At the serial Monitor I get:

<!-- begin snippet: js hide: false console: true babel: false -->

<!-- language: lang-js -->

    *WM: [2] <- HTTP WiFi save
    *WM: [3] Method: POST
    *WM: [2] Parameters
    *WM: [2] --------------------
    *WM: [2] username: test
    *WM: [2] password: test
    *WM: [2] --------------------
    *WM: [3] Sent wifi save page
    *WM: [2] processing save
    *WM: [2] Connecting as wifi client...
    *WM: [3] STA static IP:
    *WM: [2] setSTAConfig static ip not set, skipping
    *WM: [1] CONNECTED:
    *WM: [1] Connecting to NEW AP: MYSSID
    *WM: [3] Using Password: SSIDPASS
    *WM: [3] WiFi station enable
    *WM: [3] enableSTA PERSISTENT ON
    *WM: [1] connectTimeout not set, ESP waitForConnectResult...
    *WM: [2] Connection result: WL_CONNECTED
    *WM: [3] lastconxresult: WL_CONNECTED
    *WM: [1] Connect to new AP [SUCCESS]
    *WM: [1] Got IP Address:
    *WM: [1] XXX.XXX.XXX.XXX
    Should save config
    *WM: [2] disconnect configportal
    *WM: [2] restoring usermode STA
    *WM: [2] wifi status: WL_CONNECTED
    *WM: [2] wifi mode: STA
    *WM: [1] config portal exiting
    connected...yeey :)

    Connected to WiFi: MYSSID
    IP: XXX.XXX.XXX.XXX
    connected...yeey :)
    user is:

    pass is:

    user is:

    pass is:

    user is:

    pass is:

    user is:

    pass is:

<!-- end snippet -->

title: WifiManager Custom Parameters not working on ESP-01

Answers: 0


body:
I am trying to spare a few bytes of program size.
I faced a problem which I cannot understand and I hope somebody will help.

Look at this empty sketch, pleas. It takes just 444 bytes:

    void setup()
    {
    }

    void loop()
    {
    }

However, this one – 1332 bytes already!

    void f() {
     Serial.println(1);
    }

    void setup()
    {
    }

    void loop()
    {
    }

Why?
It is supposed that function `f()` will be cut-off during the linkage stage. But it is not.
And what can I do to cut such things off, since they are not used in the code?

title: Program size optimization

Answers: 1

body:
Using the `Serial` object pulls HardwareSerial0.o into your program
linkage. This file defines, among other things, the ISRs (interrupt
service routines) associated with the serial port. ISRs are defined
using [the `ISR()` macro][isr] from the acr-libc. This macro creates a
function prototype and assigns some attributes to the function,
including [the `used` attribute][used] which tells the linker that it
should consider the function to be used, even if it cannot spot a single
call to it within the compiled program. The ISR cannot then be removed,
and it in turn keeps lots of code from the `Serial` implementation.

**Edit**: As pointed out by the busybee in a comment, although `f()`
cannot be removed at link time, it can be removed at compile time if you
give it the `static` qualifier. This has the added benefit of triggering
a compiler warning:

> **warning**: '_void f()_' defined but not used [**-Wunused-function**]

[isr]: https://www.nongnu.org/avr-libc/user-manual/group__avr__interrupts.html
[used]: https://gcc.gnu.org/onlinedocs/gcc/Common-Function-Attributes.html#index-unused-function-attribute


body:
Is there any way to send and play voice between two arduino projects which has connected via blutooth modules.

1st device ( sender ) : has microphone and bluetooth module to send voice.

2nd device ( reciever ) : has bluetooth module and speaker to play that voice on real time.like an phone call.

Is this possible to do with arduino or any other microcontroller?
Thank you.

title: Is there any way to do real time voice communication via bluetooth on arduino?

Answers: 0


body:
Sometimes the arduino locks up for some reason. It would be nice to know why, but the problem is more general. I have found a hardware keep alive that resets the controller if it doesn't respond:

[Arduino Keep Alive with AT-Tiny][1]

This would work, but i wonder if there are there features like this built in to any of the processors that can be used in the Arduino environment (ESP8266, ESP32, or the like).

**Maybe folks know of a processor with the "Keep Alive" feature?**

**How would i determine if this "keep alive" feature is present for a specific processor?**

Thanks for any suggestions!

Mark

  [1]: https://diyodemag.com/projects/arduino_keepalive

title: Keep Alive for Arduino

Answers: 2

body:
personally, I have never experienced my Arduino crashing. I even have a board running for one of my university projects measuring temperature, time and resistance of a sensor and saves the data to a micro SD card that has been running for over 3 months from batteries without issues!

What do you mean by 'locks up'? If you run the blink programme, does that stop or does It work ok?

In the link you provide, the idea of resetting devices in a complex IOT project is a smart idea, but you run into the risk of having your issue repeating over and over again if you do not know what is causing the problem

body:
Reference link: https://create.arduino.cc/projecthub/rafitc/what-is-watchdog-timer-fffe20

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

* Watchdog timers can be found in the datasheet. If there is no intervention to this module by the software, the MCU will be reset. basically, restarting all the functions.
* It is a bad idea to use WDT to solve your particular topic. You should try to fix the issue
* The external watchdog timers (Example: [ADM8320][2]) is more reliable than internal ones
[![enter image description here][3]][3]

  [1]: https://i.stack.imgur.com/KVEpd.png
  [2]: https://www.analog.com/en/products/adm8320.html
  [3]: https://i.stack.imgur.com/txpjF.png


body: I have trouble with my laser sensor it doesn't work properly. When I connect all pins its doesn't work, when I remove GND and connect just the signal pin and VCC it works but the laser light is dim(I saw the light when I look at the sensor carefully ). Can someone help me?

title: Trouble with laser sensor

Answers: 0


body:
I am working with a MEGA2560 trying to implement velocity ramps for three steppers at the same time. The goal is to move to different positions applying accelerations and decelerations while finishing all of them at the same time.

In order to do so, from the distances to move of each of the motors, I calculate the amount of steps to do and the velocities for each of those steps in order to ensure that all the motors finish at the same time. For so, I use timers 3, 4 and 5 in compare mode. This way, at each interruption, I make the motors do one step and, after that, I set the new compare value for the timer in order to reach the new velocity to move at.

My problem is that, at some point, my interruptions crash and one of the motors stops working. This only happens under one condition: when motor 1 has to do 18 steps and motor 2, 34. In this case, both motors 1 and 3 finish but motor 2 gets stuck and does not move any more. Although, if its motor 1 who has to do 34 steps and motor 2, 18, everything works. Motor 1 is related to timer 3 and motor 2 to timer 4. This makes me think this must be related to the priorities of the interruptions.

In the following code you can see my interruptions:
```
ISR(TIMER3_COMPA_vect) {
    m1_step();
    m1_steps_done++;
    m1_configure_vel();
}
ISR(TIMER4_COMPA_vect) {
    m2_step();
    m2_steps_done++;
    m2_configure_vel();
}
ISR(TIMER5_COMPA_vect) {
    m3_step();
    m3_steps_done++;
    m3_configure_vel();
}
```
While, in the velocity configuration I have:
```

void m1_configure_vel() {

  if (m1_steps_done < m1_acceleration_steps) {
    m1_temp_vel = m1_temp_vel + acceleration;
  }
  else if (m1_steps_done <= (m1_steps - m1_acceleration_steps)) {
    m1_temp_vel = m1_temp_vel;
  }
  else if (m1_steps_done < m1_steps) {
    m1_temp_vel = m1_temp_vel - acceleration;
  }
  else {
    m1_temp_vel = 0;
    m1_finished = true;
  }
  if (m1_temp_vel <=0){
    m1_temp_vel = 0;
  }

  OCR3A = frequency_to_compare_value(m1_temp_vel);
}
```
As you can see, all I do here is, depending on the steps done by the motor and the amount of steps to do, I increase, maintain or decrease the motor's velocity and set the compare value for the timer.

The whole thing is that this code works fine, the ramps are calculated properly and motors move correctly. The problem is that, under the condition I explained before, interruptions may collide due to their priorities and one of them just stops to happen.

I was wondering if anyone had any idea or have faced something like this before.

title: Timer Interrupt Collision

Answers: 2

body:
I think the problem is being caused by the size of your ISR's.
When using ISR's, it's important to make the code as short as possible and you should certainly avoid using any functions!

I would change each of your ISRs to:

    ISR(TIMER3_COMPA_vect) {
        m1_steps_done++;
    }
    ISR(TIMER4_COMPA_vect) {
        m2_steps_done++;
    }
    ISR(TIMER5_COMPA_vect) {
        m3_steps_done++;
    }

then, in the main loop of your code, you can change it so that if m1_steps_done, or m2_steps_done or m3_steps_done has increased, execute the step and configure functions

body: Another approach might be to use a single timer instead of 3 separate ones.  Maintain 3 software counters and increment all of them on each interrupt, with separate limit tests and resets.  This will be slightly slower, but there will be no possibility of collisions.


body:
I have a node MCU and it hangs when I used a deep sleep, as shown in the image attached. My code looks like this:
```c++
/*
 * ESP8266 Deep sleep mode example
 * Rui Santos
 * Complete Project Details https://randomnerdtutorials.com
 */

void setup() {
  Serial.begin(115200);
  Serial.setTimeout(2000);

  // Wait for serial to initialize.
  while(!Serial) { }

  // Deep sleep mode for 30 seconds, the ESP8266 wakes up by itself when GPIO 16 (D0 in NodeMCU board) is connected to the RESET pin
  Serial.println("I'm awake, but I'm going into deep sleep mode for 30 seconds");
  ESP.deepSleep(30e6);

  // Deep sleep mode until RESET pin is connected to a LOW signal (for example pushbutton or magnetic reed switch)
  //Serial.println("I'm awake, but I'm going into deep sleep mode until RESET pin is connected to a LOW signal");
  //ESP.deepSleep(0);
}

void loop() {
}
```
[![deepsleep][1]][1]

Please help!

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

title: Deep sleep hangs when used with gpio 16 when we connect to reset pin

Answers: 1

body:
I had the same issue, and I realized I didn't connect GPIO 16 (or D1) to the RST. Sounds trivial, but happens to me.

Old topic I know, but I tried to figure out my mistake and came across this topic, so this might be helpful to some people.


body:
I wish to create a system consists of WEMOS mini & Pro-Mini sharing info using Serial ( one MCU is dedicated to react input-output, and second for MQTT commands ) sharing same Power input. From what I read in tutorials, at boot Serial wires have to be disconnected, in order to accomplish boot.

A) is that true that at boot Serial has to be disconnected?

B) is there a way that 2 MCU can be connected at all times, including reboot when needed ( such as power failures ) ?

title: Connection Pro-Mini & ESP8266 using Serial

Answers: 2

body:
> A) is that true that at boot Serial has to be disconnected?

No, that is not true. However if you are using `Serial` to communicate on the Pro Mini you will need to disconnect the ESP8266 in order to program the Pro Mini as it will interfere with serial communication to the PC.

> B) is there a way that 2 MCU can be connected at all times, including reboot when needed ( such as power failures ) ?

Given that A) is a no, then B) is irrelevant. It will just boot.

The only caveat is that the ESP8266 will squirt some boot messages out of serial as it boots at 74880 baud, so you have to be able to cope with that noise in whatever protocol you design between the two boards.

body:
> A) is that true that at boot Serial has to be disconnected?

Not exactly, if you're careful about what is communicating with what and when.  That you protect against multiple things driving the same connection, etc.  And you don't mind being very confused a lot of the time.  And that you're holding one board in reset while the other is being programmed.

> B) is there a way that 2 MCU can be connected at all times, including
> reboot when needed ( such as power failures ) ?

If you don't have a compelling reason to avoid it, you may be better off using I2C between the two of them.  Then your serial is left alone on both boards to behave as it normally does.  You don't need to sort out conflicts between boards trying to use serial to talk to each other and trying to use their serial transceivers to talk to the host and the conclusion that results from the host and both boards all see traffic from different things.  And you have an open collector setup between your two boards which makes independently powering them somewhat less of a problem.

If you do try to use the Pro Mini and ESP8266 USARTs connected together, you should have some series resistance in the connection between the FTDI (or whatever) TX signal and the RX on the Pro Mini. Or between the Pro Mini RX and the WEMOS TX.  In other words, anywhere you have two pins driving what would otherwise by the same node in the circuit, you need some current limiting in case they drive in opposite directions, as will happen if you connect their serial connections together.  If you look at the Wemos D1 mini schematic or the Arduino UNO, Nano, etc schematics you'll see they've inserted some resistance there for that reason.  If you look at the Pro Mini schematic you'll see the FTDI TX line is connected directly to the AVR's RX.

Below you asked why you would need the FTDI connection.  If you're not programming the Pro Mini and not using it power the Pro Mini, then you don't.

However, if you're thinking you're going to be able to program the Pro Mini using the serial transceiver on the Wemos and the connection between them, that isn't going to work.  The Wemos serial transceiver's TX would be connected to its ESP8266's RX, which would be connected over to the Pro Mini's TX (not RX) because project is operating normally it needs to receive data from the Pro Mini on that pin.  Allowing the Wemos serial transceiver to talk to the Pro Mini's RX would require you to wire it in a way that the two boards couldn't use their USARTs to talk to each other.  The two usages are only compatible with two different wiring schemes.


body:
I have a websocket listener that is giving me a std::string of my message payload (I want the bytes) and I wrote a function that pulls each of the bytes out and puts them into 32 bit integer variables, adds that integer to an array of 32 bit integers, and passes back the pointer address:

```
uint32_t *get32BitInt(WebsocketsMessage message)
{
  std::string raw = message.rawData();
  uint32_t chunks[message.length() / 4];
  int chunkIndex = 0;
  for (int i = 0; i < message.length(); i += 4)
  {
    uint32_t chunk = 0;
    for (int j = 0; j < 4; j++)
    {
      chunk <<= 8;
      chunk |= raw.at(i + j);
    }
    chunks[chunkIndex] = chunk;
    chunkIndex++;
  }
  return chunks;
}
```

And I know that parsing and array building works because if I add a loop before I exit the overall function call it prints them out just fine.

[![parser builds array correctly][1]][1]

And in the function that calls the parser I can print out the address of the pointer that was passed back.

But, as soon as I try to dereference anything my microcontroller crashes:

[![crash][2]][2]

I know that I'm pretty green to pointers and I'm probably misunderstanding something, but I keep looking at docs and examples of passing arrays as pointers and it seems right.

Also, something worth noting is that it doesn't seem to be an issue with the actual number printing, because if I store the first number of the array into a variable and then try to print a line after the assignment the controller crashes after the assignment but before the next serial print:

[![crash at assignment][3]][3]

  [1]: https://i.stack.imgur.com/L9eRG.png
  [2]: https://i.stack.imgur.com/HTud3.jpg
  [3]: https://i.stack.imgur.com/wYrhO.png

title: esp32 crashes when trying to dereference a pointer value

Answers: 1

body:
Ah, one of my friends pointed out the issue. It's a scope snag:

> chunks is allocated on the stack in get32BitInt By returning a pointer to chunks, you are pointing to memory that is deallocated. Think of it as pointing to a member variable of a class that has already been destroyed
>
> when you try to dereference deallocated memory, bad things can happen. usually in debug the compiler makes sure you fail hard
>
> the easiest way to test this is to allocate chunks outside of that function and pass it in as a reference

So yeah, I was allocating memory within the scope of a function and then blowing that memory contents away when that functions scope ended.

I refactored my code to move the array outside of the scope of the parsing function and passed the pointer in to the parsing function to get populated:

```
void get32BitInt(WebsocketsMessage message, uint32_t *chunks)
{
  Serial.println("--------------------------------");
  Serial.println("raw parse:");

  std::string raw = message.rawData();

  // uint32_t chunks[message.length() / 4];
  int chunkIndex = 0;

  for (int i = 0; i < message.length(); i += 4)
  {
    uint32_t chunk = 0;
    for (int j = 0; j < 4; j++)
    {
      chunk <<= 8;
      chunk |= raw.at(i + j);
    }
    chunks[chunkIndex] = chunk;
    chunkIndex++;
  }

  Serial.println("parsed chunks:");
  for (int i = 0; i < 11; i++)
  {
    Serial.print(chunks[i], HEX);
    Serial.print(" == ");
    Serial.println(chunks[i], BIN);
  }

  Serial.println("--------------------------------");
}

void addWebsocketListener()
{

  client.onMessage([&](WebsocketsMessage message) {

    uint32_t gameFrame[message.length() / 4]; // *try moving gameFrame out of scope
    get32BitInt(message, gameFrame);

    Serial.print("game frame address: ");
    Serial.println((int)&gameFrame);

    Serial.println("storing first 32 bit integer in a variable");
    uint32_t firstNumber = *gameFrame;

    Serial.print("game frame first value: ");
    Serial.println(firstNumber, HEX);

    Serial.println("printing frame:");
    for (int i = 0; i < 11; i++)
    {
      Serial.println(gameFrame[i], HEX);
    }
  });
}

```

And now my controller isn't crashing :D

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

And now I understand scope when dealing with pointers a bit better :)

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


body:
I'm working on a project of my home plants irrigation/hydroponic system(not cannabis!)) just chilies and other eatables). Also I'm trying to recycle modules, wires and other projects' leftovers such as Digispark ATtiny modules. I'd to use it as a slave controller to pass some sensors' data to master-controller. (Sensors are soil pH, moisture sensor, water counter, PIR as a cat detector).
Now I'm looking for a way to reuse Digispark USB-connector(3 and 4 pins) as a communication bus. Those pins have pull-up resistors and diodes attached to, so that's why it could be difficult.
My goal is to reduce extra components count, reuse old micro-usb wires, connect digispark slave controller using existing USB connector. And optionally save the ability to program digispark via the same connector.
I'd like to use 1-wire/i2c protocols for communication, cause it would be better to connect multiple slave-devices on the same bus.
So here are a few troubles:
1. choose of the protocol. I2C sounds better, but the popular library TinyWireS use USI pins to communicate which are different to USB pins.
1-wire looks suitable, and it also have pullup resistors on the bus.
2. voltage shift on these pins
How do you think Is it possible to connect multiple 1-wire slave digispark devices on the same bus. Do I need an optocoupler or logic level convertors?
[![Here is a schematic][1]][1]

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

title: Reusing Digispark ATtiny85 micro-USB as 1-wire bus

Answers: 0


body:
I have a project that requires rotation of a tank tread. I've simulated LED's to go off in a rotation using an IR Remote. I want to stop the clockwise rotation halfway through so I can immediately rotation counterclockwise.

Unfortunately, my code waits until after the complete rotation (or the complete while/if loop) to move into the ccw rotation loop. How do I code this to immediately switch between loops?

Here is my code:

```c++
#include <IRremote.h>

int RECV_PIN = 10;
int Switch = 10;
IRrecv irrecv(RECV_PIN);
decode_results results;

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

  pinMode(2, OUTPUT);
  pinMode(9, OUTPUT);
  pinMode(3, OUTPUT);
  pinMode(4, OUTPUT);
  pinMode(5, OUTPUT);
  pinMode(6, OUTPUT);
  pinMode(7, OUTPUT);
  pinMode(8, OUTPUT);

  irrecv.enableIRIn();         // Start the receiver
}

void loop()
{
  if (irrecv.decode(&results))
  {
    Serial.println(results.value);
    irrecv.resume();           // Receive the next value
  }

  while (results.value == 16615543)     // button 2: clockwise rotation
  {
    digitalWrite(2, HIGH);
    delay(500);                // Wait for 500 millisecond(s)

    digitalWrite(9, LOW);
    delay(1000);               // Wait for 1000 millisecond(s)

    digitalWrite(3, HIGH);
    delay(500);                // Wait for 500 millisecond(s)

    digitalWrite(2, LOW);
    delay(1000);               // Wait for 1000 millisecond(s)

    digitalWrite(4, HIGH);
    delay(500);                // Wait for 500 millisecond(s)

    digitalWrite(3, LOW);
    delay(1000);               // Wait for 1000 millisecond(s)

    digitalWrite(5, HIGH);
    delay(500);                // Wait for 500 millisecond(s)

    digitalWrite(4, LOW);
    delay(1000);               // Wait for 1000 millisecond(s)

    digitalWrite(6, HIGH);
    delay(500);                // Wait for 500 millisecond(s)

    digitalWrite(5, LOW);
    delay(1000);               // Wait for 1000 millisecond(s)

    digitalWrite(7, HIGH);
    delay(500);                // Wait for 500 millisecond(s)

    digitalWrite(6, LOW);
    delay(1000);               // Wait for 1000 millisecond(s)

    digitalWrite(8, HIGH);
    delay(500);                // Wait for 500 millisecond(s)

    digitalWrite(7, LOW);
    delay(1000);               // Wait for 1000 millisecond(s)

    digitalWrite(9, HIGH);
    delay(500);                // Wait for 500 millisecond(s)

    digitalWrite(8, LOW);
    delay(1000);               // Wait for 1000 millisecond(s)
  }

  while (results.value == 16580863)     //power button - break other loops and wait for next IR transmission
  {
    digitalWrite(2, LOW);
    digitalWrite(3, LOW);
    digitalWrite(4, LOW);
    digitalWrite(5, LOW);
    digitalWrite(6, LOW);
    digitalWrite(7, LOW);
    digitalWrite(8, LOW);
    digitalWrite(9, LOW);
  }

  while (results.value == 16619623)     // button 8: ccw rotation
  {
    digitalWrite(9, HIGH);
    delay(500);                // Wait for 500 millisecond(s)

    digitalWrite(2, LOW);
    delay(1000);               // Wait for 1000 millisecond(s)

    digitalWrite(8, HIGH);
    delay(500);                // Wait for 500 millisecond(s)

    digitalWrite(9, LOW);
    delay(1000);               // Wait for 1000 millisecond(s)

    digitalWrite(7, HIGH);
    delay(500);                // Wait for 500 millisecond(s)

    digitalWrite(8, LOW);
    delay(1000);               // Wait for 1000 millisecond(s)

    digitalWrite(6, HIGH);
    delay(500);                // Wait for 500 millisecond(s)

    digitalWrite(7, LOW);
    delay(1000);               // Wait for 1000 millisecond(s)

    digitalWrite(5, HIGH);
    delay(500);                // Wait for 500 millisecond(s)

    digitalWrite(6, LOW);
    delay(1000);               // Wait for 1000 millisecond(s)

    digitalWrite(4, HIGH);
    delay(500);                // Wait for 500 millisecond(s)

    digitalWrite(5, LOW);
    delay(1000);               // Wait for 1000 millisecond(s)

    digitalWrite(3, HIGH);
    delay(500);                // Wait for 500 millisecond(s)

    digitalWrite(4, LOW);
    delay(1000);               // Wait for 1000 millisecond(s)

    digitalWrite(2, HIGH);
    delay(500);                // Wait for 500 millisecond(s)

    digitalWrite(3, LOW);
    delay(1000);               // Wait for 1000 millisecond(s)
  }
}
```

title: How do I switch between while loops before the current loop finishes? IR Remote + LED's

Answers: 2

body:
> How do I code this to immediately switch between loops?

You don't. You remove the loops. You don't want them - they can never end, since there is no way for the results to change between iterations.

You have a fundamental misunderstanding of how IR remotes work. There can be no "while" since a remote sends a signal either just once per button press, or repeatedly while the button is held down, depending on the function the button is supposed to perform.

Instead all you can do is "If the button has been pressed then do something". There's no "It's currently pressed" or "It's been released", only "I got a signal that it's pressed".

body:
In addition to Majenko's answer, what you should use is a so called State engine.

First you define an enum:

    enum EState { Off, Clockwise, CounterClockwise };

    EState _state;

In `setup` you set  `_state` to some default value.

In `loop` you check for button changes, and set the state accordingly.

Then you act on the state:

    switch (_state)
    {
    case EState::Off:
        {
            // Switch all off
            for (int n = 0; n < 9; n++)
            {
                digitalWrite(n, LOW);
            }
        }
        break;

    case EState::Clockwise:
        ... See below

    case EState::CounterClockwise:
        ... Similar as above
    }

For the Clockwise and CounterClockwise states, you have to keep a variable, that increases every 100 ms, resets itself when going to the new state.

Depending on the step value, you do something. e.g. for the first two clockwise steps:

    digitalWrite(2, HIGH);
    delay(500);                // Wait for 500 millisecond(s)

    digitalWrite(9, LOW);
    delay(1000);               // Wait for 1000 millisecond(s)

you can make a switch like this inside the case you already have (or better: create a new function):

    switch (_step)
    {
    case 0: // 0 ms
        digitalWrite(2, HIGH);
        break;

    case 5: // 500 ms
        delay(1000);

    ...

Note it is a bit more clean to create a sort of hash/array but the above should work too. You can increase `_step` every 100 ms or only when the (counter)clockwise states are active.


body:
how can I recieve udp multicast packets in ESP8266? I have this piece of code:

    #include <ESP8266WiFi.h>
    #include <WiFiUdp.h>

    const char* ssid = "my_wifi_ssid";
    const char* password = "my_wifi_password";

    WiFiUDP Udp;
    unsigned int multicastPort = 5683;  // local port to listen on
    IPAddress multicastIP(224,0,1,187);

    void setup(){
        Serial.begin(115200);
        Serial.println();

        Serial.printf("Connecting to %s ", ssid);
        WiFi.begin(ssid, password);
        while (WiFi.status() != WL_CONNECTED)
        {
        delay(500);
        Serial.print(".");
        }
        Serial.println("connected");

        Udp.beginMulticast(WiFi.localIP(), multicastIP, multicastPort);
        Serial.printf("Now listening at IP %s and %s, UDP port %d\n", WiFi.localIP().toString().c_str(), multicastIP.toString().c_str(), multicastPort);
    }

    void loop(){
        int packetSize = Udp.parsePacket();
        if (packetSize){
        Serial.println("RECEIVED!");
        }
    }
I wrote it according to [this documentation][1] and [this addition to that about adding multicast][2].
It just set server listening on port 5683.
It prints something like:
Now listening at IP 192.168.1.6 and 224.0.1.187, UDP port 5683
But if I send UDP packet to 224.0.1.187:5683 (eg. via Packet sender app), it doesn't print message "RECEIVED!" (which should, look in loop function). Why ESP8266 is not receiving anything? Strange is, that when I send packet to 192.168.1.6:5683 (its local IP), it prints that message ("RECEIVED!").
Why it works only for local message but not for multicast??

Thanks for every help! :)

PS: [this][3] advice didn't help me...

  [1]: https://arduino-esp8266.readthedocs.io/en/latest/esp8266wifi/udp-examples.html
  [2]: https://arduino-esp8266.readthedocs.io/en/latest/esp8266wifi/udp-class.html
  [3]: https://arduino.stackexchange.com/questions/39957/esp8266-udp-multicast-doesnt-receive-packets

title: ESP8266 - How to recieve UDP multicast packet?

Answers: 1

body:
I think you need to call

    Udp.begin(multicastPort);

right before calling

    Udp.beginMulticast(WiFi.localIP(), multicastIP, multicastPort);

At least that's what did the trick for me.


body:
[![enter image description here][1]][1]I have to up the frequency by 100 hz by button press for upto 1khz; I am stuck on using the debounce source code. The problem is every time I press button the value for "i" goes to random number instead of going from 400 to 600 to 800 to 1000...to 2000.  I am using prescaler 1.
I have another question regarding the frequency. How can I get the frequency stable at 100hz per button press.

```
#define LEDPIN 7
float highTime;
float lowTime;
int freq;
float period;

//uint16_t val2= pulseIn(4, HIGH);

ISR(TIMER1_COMPA_vect) {
  digitalWrite(LEDPIN, !digitalRead(LEDPIN));
}
// constants won't change. They're used here to set pin numbers:
const int buttonPin = 5;    // the number of the pushbutton pin
//const int ledPin = 13;      // the number of the LED pin

// Variables will change:

int buttonState;             // the current reading from the input pin
int lastButtonState = LOW;   // the previous reading from the input pin

// the following variables are unsigned longs because the time, measured in
// milliseconds, will quickly become a bigger number than can be stored in an int.
unsigned long lastDebounceTime = 0;  // the last time the output pin was toggled
unsigned long debounceDelay = 50;    // the debounce time; increase if the output flickers

void setup() {

  Serial.begin(9600);
  pinMode(buttonPin, INPUT_PULLUP);
  //pinMode(ledPin, OUTPUT);

  // set initial LED state
  //digitalWrite(ledPin, ledState);

  pinMode(LEDPIN, OUTPUT);
  // initialize Timer1 (the 16-bit timer) using channel A output compare

  TCCR1A = 0; // set entire TCCR1A register to 0
  TCCR1B = 0; // same for TCCR1B
  TCNT1 = 0; // initialize counter value to 0
  // set compare match register for 100 Hz increments
  OCR1A = 9999; // = 16000000 / (8 * 100) - 1 (must be <65536)
  // turn on CTC mode
  TCCR1B |= (1 << WGM12);
  // Set CS12, CS11 and CS10 bits for 1 prescaler
  TCCR1B |= (0 << CS12) | (1 << CS11) | (0 << CS10);

  // enable timer compare interrupt
  TIMSK1 |= (1 << OCIE1A);
  sei(); // allow interrupts
  interrupts(); // enable global interrupts:
}

void loop() {

  // read the state of the switch into a local variable:
  int reading = digitalRead(buttonPin);
  int MIN = 400;
  int MAX = 2000;
  int i = 0;
  int change = 200;
  int var = 16000000 / (1 * i) - 1 ;
  // check to see if you just pressed the button
  // (i.e. the input went from LOW to HIGH), and you've waited long enough
  // since the last press to ignore any noise:

  // If the switch changed, due to noise or pressing:
  if (reading != lastButtonState) {
    // reset the debouncing timer
    lastDebounceTime = millis();
  }
  for (int i = 400; i <= 2000; i += change) {
    if ((millis() - lastDebounceTime) > debounceDelay) {

      // whatever the reading is at, it's been there for longer than the debounce
      // delay, so take it as the actual current state:

      // if the button state has changed:
      if (reading != buttonState) {
        buttonState = reading;

        // only toggle the LED if the new button state is HIGH
        //for(int ii=MIN; ii<MAX; ii++){
        //

        if (buttonState == HIGH) {
          Serial.print("Value of i: ");
          Serial.println(i);

          //for(int i=MIN; i <= MAX; i+=change){
          //int var = 16000000 / (1 * (ii*2)) - 1 ;
          buttonState != buttonState;
          TCCR1A = 0; // set entire TCCR1A register to 0
          TCCR1B = 0; // same for TCCR1B
          TCNT1  = 0; // initialize counter value to 0
          OCR1A = 16000000 / (1 * i) - 1; // =  (must be <65536)
          // turn on CTC mode
          TCCR1B |= (1 << WGM12);
          // Set CS12, CS11 and CS10 bits for 1 prescaler
          TCCR1B |= (0 << CS12) | (0 << CS11) | (1 << CS10);
          // enable timer compare interrupt
          TIMSK1 |= (1 << OCIE1A);
          highTime = (pulseIn(4, HIGH));
          lowTime = (pulseIn(4, LOW));
          period = highTime + lowTime;
          freq = 1000000 / period;   //getting frequency with totalTime is in Micro seconds
          Serial.print(freq);
          Serial.print("\n");
        }
        //}
        //  }

      }
    }
  }

  // save the reading. Next time through the loop, it'll be the lastButtonState:
  lastButtonState = reading;

}
```

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

title: Changing frequency by button press

Answers: 0


body:
I'm working on a self-balancing robot. The self-balancing is not the issue. The issue is that the motors don't respond as they are supposed to.

I would understand if it were unable to balance, but the motors are not reacting to the tilt at all. The motors aren't responding to the lines of code that are telling them to move, despite being wired correctly.

I turn on the system and it spins one motor and usually in one direction, but at times it will slow down or change direction. This change does not occur consistently which I am sure of. Moving the robot to the exact same rotation and back gives different results each time.

I have checked the voltage with a multimeter, 4.9V at the Arduino 5V pin. I have a 9V battery connected to the barrel jack (Vin) 8.26V in. I know this Arduino and MPU5060 are not broken and are in fact connected correctly because when I run the serial monitor it shows me the tilt in degrees on my laptop.

A list of tests I did and what they showed me:

1: All voltages were what they should be at 5V pin and Vin according to my multimeter. The 5V on the MPU6050 was also the same as the 5V on the Arduino obviously as it's the same node.

2:  I tried a blink sketch to see if the Arduino was working when plugged into the battery (9V) instead of the computer cord. It blinked as it should, showing that indeed it had sufficient power from the battery and was working correctly. I now know the Arduino is working and is not underpowered.

3: I tested if the MPU6050 was functioning on the battery power (powered off Arduino which is powered off the 9V). I made a sketch that turned on the onboard LED if the MPU6050 was past 0 degrees. This test worked consistently When it was tilted between -1 and -90 degrees it turned the LED on. When I positioned it back up to 0 degrees or past 0 it turned the light off. So now I know conclusively that the Arduino and MPU6050 are functioning and not being underpowered.

4: I tested both motors individually disconnected from the l298n, with a 6V 4AA battery pack and both spun like they should.

5: When I disconnect the two PWM pins and put the tiny jumpers on the l298n back in place both wheels turn in the same direction at a consistant speed but do not react to the tilt at all. They continuously move in that direction and nothing stops them from spinning until I unplug it.

```c++
#include "Wire.h"
#include "I2Cdev.h"
#include "MPU6050.h"
#include "math.h"

#define leftMotorPWMPin 5
#define leftMotorGoForward 6
#define leftMotorGoBack 7
#define rightMotorGoForward 8
#define rightMotorGoBack 9
#define rightMotorPWMPin 10

int16_t accY, accZ;
float accAngle;

MPU6050 mpu;

void setup() {
  // set the motor control and PWM pins to output mode
  pinMode(leftMotorPWMPin, OUTPUT);
  pinMode(leftMotorGoForward, OUTPUT);
  pinMode(leftMotorGoBack, OUTPUT);

  pinMode(rightMotorGoForward, OUTPUT);
  pinMode(rightMotorGoBack, OUTPUT);
  pinMode(rightMotorPWMPin, OUTPUT);
  // set the status LED to output mode
  mpu.initialize();
  Serial.begin(9600);
}

void loop() {
  //delay(100);
  accZ = mpu.getAccelerationZ();
  accY = mpu.getAccelerationY();
  accAngle = atan2(accY, accZ)*RAD_TO_DEG;

  if (isnan(accAngle));
  else
    Serial.println(accAngle);

  if ((accAngle <= 5) && (accAngle > 0)) {
    analogWrite(leftMotorPWMPin, 42.5);
    digitalWrite(leftMotorGoForward, HIGH);
    digitalWrite(leftMotorGoBack, LOW);

    analogWrite(leftMotorPWMPin, 42.5);
    digitalWrite(rightMotorGoForward, HIGH);
    digitalWrite(rightMotorGoBack, LOW);
  }
  else if (accAngle == 0) {
    analogWrite(leftMotorPWMPin, 0);
    digitalWrite(leftMotorGoForward, LOW);
    digitalWrite(leftMotorGoBack, LOW);

    analogWrite(leftMotorPWMPin, 0);
    digitalWrite(rightMotorGoForward, LOW);
    digitalWrite(rightMotorGoBack, LOW);
  }
  else if ((accAngle <= 15) && (accAngle > 5)) {
    analogWrite(leftMotorPWMPin, 85);
    digitalWrite(leftMotorGoForward, HIGH);
    digitalWrite(leftMotorGoBack, LOW);

    analogWrite(leftMotorPWMPin, 85);
    digitalWrite(rightMotorGoForward, HIGH);
    digitalWrite(rightMotorGoBack, LOW);
  }
  else if ((accAngle <= 30) && (accAngle > 15)) {
    analogWrite(leftMotorPWMPin, 127.5);
    digitalWrite(leftMotorGoForward, HIGH);
    digitalWrite(leftMotorGoBack, LOW);

    analogWrite(leftMotorPWMPin, 127.5);
    digitalWrite(rightMotorGoForward, HIGH);
    digitalWrite(rightMotorGoBack, LOW);
  }
  else if ((accAngle <= 45) && (accAngle > 30)) {
    analogWrite(leftMotorPWMPin, 170);
    digitalWrite(leftMotorGoForward, HIGH);
    digitalWrite(leftMotorGoBack, LOW);

    analogWrite(leftMotorPWMPin, 170);
    digitalWrite(rightMotorGoForward, HIGH);
    digitalWrite(rightMotorGoBack, LOW);
  }
  else if ((accAngle <= 65) && (accAngle > 45)) {
    analogWrite(leftMotorPWMPin, 212.5);
    digitalWrite(leftMotorGoForward, HIGH);
    digitalWrite(leftMotorGoBack, LOW);

    analogWrite(leftMotorPWMPin, 212.5);
    digitalWrite(rightMotorGoForward, HIGH);
    digitalWrite(rightMotorGoBack, LOW);
  }
  else if ((accAngle <= 90) && (accAngle > 65)) {
    analogWrite(leftMotorPWMPin, 255);
    digitalWrite(leftMotorGoForward, HIGH);
    digitalWrite(leftMotorGoBack, LOW);

    analogWrite(leftMotorPWMPin, 255);
    digitalWrite(rightMotorGoForward, HIGH);
    digitalWrite(rightMotorGoBack, LOW);
  }

  //These next bunch are identical but for the negative (if it falls backwards)

  if ((accAngle >= -5) && (accAngle < 0)) {
    analogWrite(leftMotorPWMPin, 42.5);
    digitalWrite(leftMotorGoForward, LOW);
    digitalWrite(leftMotorGoBack, HIGH);

    analogWrite(leftMotorPWMPin, 42.5);
    digitalWrite(rightMotorGoForward, LOW);
    digitalWrite(rightMotorGoBack, HIGH);
  }
  else if ((accAngle >= -15) && (accAngle < -5)) {
    analogWrite(leftMotorPWMPin, 85);
    digitalWrite(leftMotorGoForward, LOW);
    digitalWrite(leftMotorGoBack, HIGH);

    analogWrite(leftMotorPWMPin, 85);
    digitalWrite(rightMotorGoForward, LOW);
    digitalWrite(rightMotorGoBack, HIGH);
  }
  else if ((accAngle >= -30) && (accAngle < -15)) {
    analogWrite(leftMotorPWMPin, 127.5);
    digitalWrite(leftMotorGoForward, LOW);
    digitalWrite(leftMotorGoBack, HIGH);

    analogWrite(leftMotorPWMPin, 127.5);
    digitalWrite(rightMotorGoForward, LOW);
    digitalWrite(rightMotorGoBack, HIGH);
  }
  else if ((accAngle >= -45) && (accAngle < -30)) {
    analogWrite(leftMotorPWMPin, 170);
    digitalWrite(leftMotorGoForward, LOW);
    digitalWrite(leftMotorGoBack, HIGH);

    analogWrite(leftMotorPWMPin, 170);
    digitalWrite(rightMotorGoForward, LOW);
    digitalWrite(rightMotorGoBack, HIGH);
  }
  else if ((accAngle >= -65) && (accAngle < -45)) {
    analogWrite(leftMotorPWMPin, 212.5);
    digitalWrite(leftMotorGoForward, LOW);
    digitalWrite(leftMotorGoBack, HIGH);

    analogWrite(leftMotorPWMPin, 212.5);
    digitalWrite(rightMotorGoForward, LOW);
    digitalWrite(rightMotorGoBack, HIGH);
  }
  else if ((accAngle >= -90) && (accAngle < 65)) {
    analogWrite(leftMotorPWMPin, 255);
    digitalWrite(leftMotorGoForward, LOW);
    digitalWrite(leftMotorGoBack, HIGH);

    analogWrite(leftMotorPWMPin, 255);
    digitalWrite(rightMotorGoForward, LOW);
    digitalWrite(rightMotorGoBack, HIGH);
  }
}
```

I am aware this is an unconventional way of programming for a self balancing robot, that is not my problem so don't mention it please and thank you!

Anyone have any ideas to what could be the source of the issue? Is it possible one of the libraries is using the PWM pins in the background?

All out of ideas, the motor controller board is practically brand new I highly doubt it's broken.

Schematic:

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

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

title: l298N PWM motor control with Uno is not functioning correctly

Answers: 0


body:
I have 3 micro-controllers that will be connected to a battery, and I need to provide each of them between 3 and 5 volts maximum.

I have 3V batteries but they do not seem to provide enough power, while putting to of them in series would fry the chips as it busts the 6 volts max.

My question is, if I provide 9 volts to 3 chips connected in series, would current drop be distributed evenly to 3V across all chips, or would for example fry the first one?

<!-- Begin schematic: In order to preserve an editable schematic, please
     don't edit this section directly.
     Click the "edit" link below the image in the preview instead. -->

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

<!-- End schematic -->

title: Chips & High voltage: Connected in Series?

Answers: 1

body:
If  you put three resistors of the same value in series, then you would get equal voltage division between them.

But chips are not like resistors. Their current usage is not constant and typically vary by orders of magnitude even within each clock cycle. See why this would be a problem?

If you have good 3V batteries that supply 3V up to the maximum current that the chips can draw, and the chips are rated to run reliably at 3V then there is another problem. Maybe you need decoupling capacitors across the chips?


body:
I am currently trying to determine how the [ESP8266 WifiSniffer program by Kalanda][1] works.

Here is the source code:

    #include <Arduino.h>

    extern "C" {
      #include <user_interface.h>
    }

    #define DATA_LENGTH           112

    #define TYPE_MANAGEMENT       0x00
    #define TYPE_CONTROL          0x01
    #define TYPE_DATA             0x02
    #define SUBTYPE_PROBE_REQUEST 0x04

    struct RxControl {
    //THESE HAVE AN EFFECT
    // signed rssi:8; // signal intensity of packet
    // unsigned rate:4;
    // unsigned is_group:1;
    // unsigned:1;
    // unsigned legacy_length:12; // if not 11n packet, shows length of packet. NOT THIS
    // unsigned MCS:7; // if is 11n packet, shows the modulation and code used (range from 0 to 76)
    // unsigned Smoothing:1;
    // unsigned Not_Sounding:1;
    // unsigned:1;
    // unsigned Aggregation:1;
    // unsigned STBC:2;
    // unsigned rxend_state:8;
    // unsigned ampdu_cnt:8;
    // unsigned channel:4; //which channel this packet in.

    //THESE HAVE NO EFFECT
    // unsigned sig_mode:2; // 0:is 11n packet; 1:is not 11n packet;
    // unsigned damatch0:1;
    // unsigned damatch1:1;
    // unsigned bssidmatch0:1;
    // unsigned bssidmatch1:1;
    // unsigned CWB:1; // if is 11n packet, shows if is HT40 packet or not
    // unsigned HT_length:16;// if is 11n packet, shows length of packet. NOT THIS
     //unsigned FEC_CODING:1; // if is 11n packet, shows if is LDPC packet or not.
     //unsigned SGI:1;
     //unsigned:12; //HAS NO EFFECT
    };

    struct SnifferPacket{
        struct RxControl rx_ctrl; //RxControl is just a name, can be named anything (as long as you change other things)
        uint8_t data[DATA_LENGTH]; //DOES NOT HAVE EFFECT
    //    uint16_t cnt; //THIS HAS NO EFFECT
    //    uint16_t len; //THIS HAS NO EFFECT
    };

    // Declare each custom function (excluding built-in, such as setup and loop) before it will be called.
    // https://docs.platformio.org/en/latest/faq.html#convert-arduino-file-to-c-manually
    //static void showMetadata(SnifferPacket *snifferPacket);
    //static void sniffer_callback(uint8_t *buffer, uint16_t length);
    static void printDataSpan(uint16_t start, uint16_t size, uint8_t* data);
    static void getMAC(char *addr, uint8_t* data, uint16_t offset);
    void channelHop();

    /**
     * Callback for promiscuous mode
     */
    static void sniffer_callback(uint8_t *buffer, uint16_t length) {

      struct SnifferPacket *snifferPacket;
      snifferPacket = (struct SnifferPacket*) buffer;

      Serial.print("buffer size: ");
      Serial.print(sizeof(buffer));

      Serial.print(" length size: ");
      Serial.print(sizeof(length));

      Serial.print(" snifferPacket size: ");
      Serial.print(sizeof(snifferPacket));

      Serial.print(" START OF BUFFER OG: ");
      for (int i = 0; i < 20; i++){
        Serial.print((unsigned int) buffer[i], BIN);
        Serial.print(" ");
      }
      Serial.print(" END OF BUFFER OG ");

      showMetadata(snifferPacket);
    }

    static void showMetadata(SnifferPacket *snifferPacket) {

      unsigned int frameControl = ((unsigned int)snifferPacket->data[1] << 8) + snifferPacket->data[0];

      uint8_t version        = (frameControl & 0b0000000000000011) >> 0;
      uint8_t frameType      = (frameControl & 0b0000000000001100) >> 2;
      uint8_t frameSubType   = (frameControl & 0b0000000011110000) >> 4;
      uint8_t toDS           = (frameControl & 0b0000000100000000) >> 8;
      uint8_t fromDS         = (frameControl & 0b0000001000000000) >> 9;
      uint8_t moreFragments  = (frameControl & 0b0000010000000000) >> 10;
      uint8_t retry          = (frameControl & 0b0000100000000000) >> 11;
      uint8_t powerMgmt      = (frameControl & 0b0001000000000000) >> 12;
      uint8_t moreData       = (frameControl & 0b0010000000000000) >> 13;
      uint8_t protectedFrame = (frameControl & 0b0100000000000000) >> 14;
      uint8_t htcOrder       = (frameControl & 0b1000000000000000) >> 15;

      Serial.print(" START OF BUFFER: ");
      for (int i = 0; i < 20; i++){
        Serial.print((unsigned int)snifferPacket->data[i], BIN);
        Serial.print(" ");
      }
      Serial.print(" END OF BUFFER ");

      Serial.print(" DATASPAN START: ");
      printDataSpan;
      Serial.print(" DATASPAN END ");

      Serial.print(" frameControl: ");
      Serial.print(frameControl);

      Serial.print(" version: ");
      Serial.print(version);

      Serial.print(" Type: ");
      Serial.print(frameType);

      Serial.print(" frameSubType: ");
      Serial.print(frameSubType);

      Serial.print(" toDS: ");
      Serial.print(toDS);

      Serial.print(" fromDS: ");
      Serial.print(fromDS);

      Serial.print(" moreFragments: ");
      Serial.print(moreFragments);

      Serial.print(" retry: ");
      Serial.print(retry);

      Serial.print(" powerMgmt: ");
      Serial.print(powerMgmt);

      Serial.print(" moreData: ");
      Serial.print(moreData);

      Serial.print(" protectedFrame: ");
      Serial.print(protectedFrame);

      Serial.print(" htcOrder: ");
      Serial.print(htcOrder);

      Serial.print(" Ch: ");
      Serial.print(wifi_get_channel());

    //  Serial.print(" rssi: ");
    //  Serial.print(snifferPacket->rx_ctrl.rssi, BIN);

    //  Serial.print(" RSSI: ");
    //  Serial.print(snifferPacket->rx_ctrl.rssi, DEC);

      //Only look for probe request packets
    //  if (frameType != TYPE_MANAGEMENT ||
    //      frameSubType != SUBTYPE_PROBE_REQUEST)
    //        //Serial.println();
    //        return;

    //  Serial.print(" RSSI: ");
    //  Serial.print(snifferPacket->rx_ctrl.rssi, DEC);

      Serial.print(" Ch: ");
      Serial.print(wifi_get_channel());

      char addr[] = "00:00:00:00:00:00";
      getMAC(addr, snifferPacket->data, 10);
      Serial.print(" Peer MAC: ");
      Serial.print(addr);

    //  uint8_t SSID_length = snifferPacket->data[25];
    //  Serial.print(" SSID: ");printDataSpan
    //  printDataSpan(26, SSID_length, snifferPacket->data);

      Serial.println();
    }

    static void printDataSpan(uint16_t start, uint16_t size, uint8_t* data) {
      for(uint16_t x = start; x < DATA_LENGTH && x < start+size; x++) {
        Serial.print(data[x]);
        //Serial.write(data[x]);
      }
    }

    static void getMAC(char *addr, uint8_t* data, uint16_t offset) {
      sprintf(addr, "x:x:x:x:x:x", data[offset+0], data[offset+1], data[offset+2], data[offset+3], data[offset+4], data[offset+5]);
    }

    #define CHANNEL_HOP_INTERVAL_MS   100
    static os_timer_t channelHop_timer;

    /**
     * Callback for channel hoping
     */
    void channelHop()
    {
      // hoping channels 1-13
      uint8 new_channel = wifi_get_channel() + 1;
      if (new_channel > 13) {
        new_channel = 1;
      }
      wifi_set_channel(new_channel);
    }

    #define DISABLE 0
    #define ENABLE  1

    void setup() {
      // set the WiFi chip to "promiscuous" mode aka monitor mode
      Serial.begin(115200);
      //delay(10);
      wifi_set_opmode(STATION_MODE);
      wifi_set_channel(1);
      wifi_promiscuous_enable(DISABLE);
      //delay(10);
      wifi_set_promiscuous_rx_cb(sniffer_callback);
      //delay(10);
      wifi_promiscuous_enable(ENABLE);

      // setup the channel hoping callback timer
      //os_timer_disarm(&channelHop_timer);
      //os_timer_setfn(&channelHop_timer, (os_timer_func_t *) channelHop, NULL);
      //os_timer_arm(&channelHop_timer, CHANNEL_HOP_INTERVAL_MS, 1);
    }

    void loop() {
      //delay(10);
    }

I have noticed the `Serial.print` output directly from the `buffer` differs to the `Serial.print` output for the variable `snifferPacket` which is given attributes of the struct `RxControl`.

When the code is configured as normal, the raw buffer output (BUFFER OG) has 12 additional elements compared to the snifferPacket (BUFFER) output.
Here is an example:

    buffer size: 4 length size: 2 snifferPacket size: 4 START OF BUFFER OG: 10100010 10000 11100110 1010000 0 0 0 0 0 0 1 0 10000000 0 0 0 11111111 11111111 11111111 11111111  END OF BUFFER OG  START OF BUFFER: 10000000 0 0 0 11111111 11111111 11111111 11111111 11111111 11111111 11011000 111 10110110 11010 10100010 1000001 11011000 111 10110110 11010  END OF BUFFER  DATASPAN START:  DATASPAN END  frameControl: 128 version: 0 Type: 0 frameSubType: 8 toDS: 0 fromDS: 0 moreFragments: 0 retry: 0 powerMgmt: 0 moreData: 0 protectedFrame: 0 htcOrder: 0 Ch: 1 Ch: 1 Peer MAC: d8:07:b6:1a:a2:41

Comparing just the two buffer outputs:

     - BUFFER OG: 10100010 10000 11100110 1010000 0 0 0 0 0 0 1 0 10000000 0
       0 0 11111111 11111111 11111111 11111111
     - BUFFER: 10000000 0 0 0 11111111 11111111 11111111 11111111...

I've been able to identify parts of the first 12 elements:

    1.  10100010 -> RCPI (RSSI) in two's complement format
    2.  10000    -> Unknown
    3.  11100110 -> Unknown
    4.  1010000  -> Unknown
    5.  0        -> Unknown, but constant
    6.  0        -> Unknown, but constant
    7.  0        -> Unknown, but constant
    8.  0        -> Unknown, but constant
    9.  0        -> Unknown, but constant
    10. 0        -> Unknown, but constant
    11. 1        -> Wi-Fi channel (in this example it's channel 1)
    12. 0        -> Unknown, but constant

These 12 elements come before the 802.11 packet (starting with the frame header which begins at 10000000)

Through trial and error, I've been able to the identify parts of the code that effect the snifferPacket output. These are:
 1. 14 attributes in the `RxControl` struct, titled as `THESE HAVE AN EFFECT`.

       a. Commenting between 1-8 of any attributes: The last 4 elements appear in the `snifferPacket` output (`0 0 1 0`)

       b. Commenting between 9-13 of any attributes: The last 8 elements appear in the `snifferPacket` output (`0 0 0 0 0 0 1 0`)

       c. Commenting all 14 attributes: The last 11 elements appear in the snifferPacket output (`10000 11100110 1010000 0 0 0 0 0 0 1 0`)

 2. `struct RxControl rx_ctrl;`, under `struct SnifferPacket`

    a. Commenting out: All 12 elements appear in the snifferPacket output (`10100010 10000 11100110 1010000 0 0 0 0 0 0 1 0`)

So it's clear that there is an association between defining attributes and their exclusion from the snifferPacket output.

Note that leading 0s are part of an element are ignored are part of the output. For example:

     - 0100 = 100
     - 0000 = 0
     - 1000 = 1000

 So my questions are:

 1. What do each of the 12 elements represent?
 2. Why is there a difference in the output between the output of the raw `buffer` and `snifferPacket`?
 3. Why do only certain attributes effect the output of `snifferPacket`?
 4. Why does commenting a greater number of attributes result in a greater number of elements reappearing, no matter which attributes are commented?

Thanks in advance.

  [1]: https://github.com/kalanda/esp8266-sniffer

title: Elements excluded from buffer array output after given structure (ESP8266 WifiSniffer) (snifferPacket)

Answers: 1

body:
> What do each of the 12 elements represent?

Things in the header. That is off-topic for here.

> Why is there a difference in the output between the output of the raw buffer and snifferPacket?

snifferPacket is overlaid over the incoming buffer. That includes the "data" buffer which you are printing. The data buffer is only a portion of the snifferPacket.

> Why do only certain attributes effect the output of snifferPacket?

They are bit fields, and they are packed into bytes or words. The number and size of bit fields affects the number of bytes needed to contain them, and thus where in the structure the `data` array comes.

> Why does commenting a greater number of attributes result in a greater number of elements reappearing, no matter which attributes are commented?

See above. Also, the attributes must be there. Removing them will mean that other attributes don't point to the right bits in memory.

You should learn how C bit fields work. You can read more at the C++ reference [here](https://en.cppreference.com/w/cpp/language/bit_field).


body:
I am using a GSM MC60E Shield (Model: https://forum.arduino.cc/index.php?topic=234200.0) on top of an Arduino Mega 2560; the Arduino is connected to other sensors that are not important now.
I want to take values stored in the Arduino Mega and send them via the GSM MC60E Shield to my phone every 12h.
But I am stuck at a previous step: the GSM MC60E can't connect to the network. I turn it on by holding the power button for 4s, the redLED is supposed to flash every 2s when it is on. I am not sure if...

- It is a problem of the code. I read rx and tx should be connected opposite. But since it is a shield, how can I oppose them?
- It is a physical connection problem (weird because there are no cables or anything, only the shield on top of the Arduino and the USB Port to the computer)

So far this is the code that has worked. It stops at the output "Waiting for Network..." and then "fail":

    /**********************
     *
     * This sketch connects to a website and downloads a page.
     * It can be used to perform HTTP/RESTful API calls.
     *
     * TinyGSM Getting Started guide:
     *   https://tiny.cc/tinygsm-readme
     *
     **********************/

    // Select your modem:
    //#define TINY_GSM_MODEM_SIM800
    // #define TINY_GSM_MODEM_SIM808
    // #define TINY_GSM_MODEM_SIM868
    // #define TINY_GSM_MODEM_SIM900
    // #define TINY_GSM_MODEM_SIM7000
    // #define TINY_GSM_MODEM_SIM5360
    // #define TINY_GSM_MODEM_SIM7600
    // #define TINY_GSM_MODEM_UBLOX
    // #define TINY_GSM_MODEM_SARAR4
    // #define TINY_GSM_MODEM_M95
    // #define TINY_GSM_MODEM_BG96
    // #define TINY_GSM_MODEM_A6
    // #define TINY_GSM_MODEM_A7
    // #define TINY_GSM_MODEM_M590
    // #define TINY_GSM_MODEM_MC60
    #define TINY_GSM_MODEM_MC60E
    // #define TINY_GSM_MODEM_ESP8266
    // #define TINY_GSM_MODEM_XBEE
    // #define TINY_GSM_MODEM_SEQUANS_MONARCH

    // Set serial for debug console (to the Serial Monitor, default speed 115200)
    #define SerialMon Serial

    // Set serial for AT commands (to the module)
    // Use Hardware Serial on Mega, Leonardo, Micro
    #define SerialAT Serial1

    // or Software Serial on Uno, Nano
    //#include <SoftwareSerial.h>
    //SoftwareSerial SerialAT(1, 0); // RX, TX

    // Increase RX buffer to capture the entire response
    // Chips without internal buffering (A6/A7, ESP8266, M590)
    // need enough space in the buffer for the entire response
    // else data will be lost (and the http library will fail).
    #if !defined(TINY_GSM_RX_BUFFER)
    #define TINY_GSM_RX_BUFFER 650
    #endif

    // See all AT commands, if wanted
    // #define DUMP_AT_COMMANDS

    // Define the serial console for debug prints, if needed
    #define TINY_GSM_DEBUG SerialMon

    // Range to attempt to autobaud
    #define GSM_AUTOBAUD_MIN 9600
    #define GSM_AUTOBAUD_MAX 115200

    // Add a reception delay - may be needed for a fast processor at a slow baud rate
    // #define TINY_GSM_YIELD() { delay(2); }

    // Uncomment this if you want to use SSL
    // #define USE_SSL

    // Define how you're planning to connect to the internet
    #define TINY_GSM_USE_GPRS true
    #define TINY_GSM_USE_WIFI false

    // set GSM PIN, if any
    #define GSM_PIN ""

    // Your GPRS credentials, if any
    const char apn[]  = "YourAPN";
    const char gprsUser[] = "";
    const char gprsPass[] = "";

    // Your WiFi connection credentials, if applicable
    const char wifiSSID[]  = "YourSSID";
    const char wifiPass[] = "YourWiFiPass";

    // Server details
    const char server[] = "vsh.pp.ua";
    const char resource[] = "/TinyGSM/logo.txt";

    #include <TinyGsmClient.h>

    // Just in case someone defined the wrong thing..
    #if TINY_GSM_USE_GPRS && not defined TINY_GSM_MODEM_HAS_GPRS
    #undef TINY_GSM_USE_GPRS
    #undef TINY_GSM_USE_WIFI
    #define TINY_GSM_USE_GPRS false
    #define TINY_GSM_USE_WIFI true
    #endif
    #if TINY_GSM_USE_WIFI && not defined TINY_GSM_MODEM_HAS_WIFI
    #undef TINY_GSM_USE_GPRS
    #undef TINY_GSM_USE_WIFI
    #define TINY_GSM_USE_GPRS true
    #define TINY_GSM_USE_WIFI false
    #endif

    #ifdef DUMP_AT_COMMANDS
      #include <StreamDebugger.h>
      StreamDebugger debugger(SerialAT, SerialMon);
      TinyGsm modem(debugger);
    #else
      TinyGsm modem(SerialAT);
    #endif

    #ifdef USE_SSL
      TinyGsmClientSecure client(modem);
      const int  port = 443;
    #else
      TinyGsmClient client(modem);
      const int  port = 80;
    #endif

    void setup() {
      // Set console baud rate
      SerialMon.begin(115200);
      delay(10);

      // !!!!!!!!!!!
      // Set your reset, enable, power pins here
      // !!!!!!!!!!!

      SerialMon.println("Wait...");

      // Set GSM module baud rate
      TinyGsmAutoBaud(SerialAT, GSM_AUTOBAUD_MIN, GSM_AUTOBAUD_MAX);
      // SerialAT.begin(9600);
      delay(6000);

      // Restart takes quite some time
      // To skip it, call init() instead of restart()
      SerialMon.println("Initializing modem...");
      modem.restart();
      // modem.init();

      String modemInfo = modem.getModemInfo();
      SerialMon.print("Modem Info: ");
      SerialMon.println(modemInfo);

    #if TINY_GSM_USE_GPRS
      // Unlock your SIM card with a PIN if needed
      if ( GSM_PIN && modem.getSimStatus() != 3 ) {
        modem.simUnlock(GSM_PIN);
      }
    #endif
    }

    void loop() {

    #if TINY_GSM_USE_WIFI
      // Wifi connection parameters must be set before waiting for the network
      SerialMon.print(F("Setting SSID/password..."));
      if (!modem.networkConnect(wifiSSID, wifiPass)) {
        SerialMon.println(" fail");
        delay(10000);
        return;
      }
      SerialMon.println(" success");
    #endif

    #if TINY_GSM_USE_GPRS && defined TINY_GSM_MODEM_XBEE
      // The XBee must run the gprsConnect function BEFORE waiting for network!
      modem.gprsConnect(apn, gprsUser, gprsPass);
    #endif

      SerialMon.print("Waiting for network...");
      if (!modem.waitForNetwork()) {
        SerialMon.println(" fail");
        delay(10000);
        return;
      }
      SerialMon.println(" success");

      if (modem.isNetworkConnected()) {
        SerialMon.println("Network connected");
      }

    #if TINY_GSM_USE_GPRS
      // GPRS connection parameters are usually set after network registration
        SerialMon.print(F("Connecting to "));
        SerialMon.print(apn);
        if (!modem.gprsConnect(apn, gprsUser, gprsPass)) {
          SerialMon.println(" fail");
          delay(10000);
          return;
        }
        SerialMon.println(" success");

      if (modem.isGprsConnected()) {
        SerialMon.println("GPRS connected");
      }
    #endif

      SerialMon.print("Connecting to ");
      SerialMon.println(server);
      if (!client.connect(server, port)) {
        SerialMon.println(" fail");
        delay(10000);
        return;
      }
      SerialMon.println(" success");

      // Make a HTTP GET request:
      SerialMon.println("Performing HTTP GET request...");
      client.print(String("GET ") + resource + " HTTP/1.1\r\n");
      client.print(String("Host: ") + server + "\r\n");
      client.print("Connection: close\r\n\r\n");
      client.println();

      uint32_t timeout = millis();
      while (client.connected() && millis() - timeout < 10000L) {
        // Print available data
        while (client.available()) {
          char c = client.read();
          SerialMon.print(c);
          timeout = millis();
        }
      }
      SerialMon.println();

      // Shutdown

      client.stop();
      SerialMon.println(F("Server disconnected"));

    #if TINY_GSM_USE_WIFI
        modem.networkDisconnect();
        SerialMon.println(F("WiFi disconnected"));
    #endif
    #if TINY_GSM_USE_GPRS
        modem.gprsDisconnect();
        SerialMon.println(F("GPRS disconnected"));
    #endif

      // Do nothing forevermore
      while (true) {
        delay(1000);
      }
    }

Thanks in advance :)

title: MC60E GSM Shield can't connect to Network

Answers: 0


body:
I am trying to run a stepper motor using an Arduino stepper motor shield like the [Adafruit V1 motor shield][1]. In my code I am just trying to get the motor to rotate forwards and backwards. When I first try uploading and running the code I can get a forward and reverse rotation, but then the motor begins jittering inconsistently. I have tried changing my wiring setup but generally get the same results. [Here is the data sheet][2] for the motor I am using. I have the board it connected to a 12v battery. I also got the same problem when trying to drive the motor using just an H-drive chip. I have included my code below as well as a picture of my wiring. [Here is a video of the jitter][3].

    #include <AFMotor.h>
    AF_Stepper motor(200, 1);
    void setup() {
    Serial.begin(9600);           // set up Serial library at 9600 bps
    Serial.println("Stepper test!");

    motor.setSpeed(120);  // 10 rpm

    motor.step(100, FORWARD, SINGLE);
    motor.release();
    delay(1000);
    }

    void loop() {
    motor.step(200, FORWARD, DOUBLE);

    delay(1000);
    motor.step(200, BACKWARD, DOUBLE);
    delay(1000);
    }

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

  [1]: https://www.adafruit.com/product/81
  [2]: https://datasheetspdf.com/pdf/1310364/Handson/17HS4401S/1
  [3]: https://youtu.be/L0Yi0MTBdww
  [4]: https://i.stack.imgur.com/vAHt5.jpg

title: Stepper Motor Inconsistent Jittering

Answers: 0


body:
OK I have the Logitech G29 Wheel and Pedal setup that I use for my Racing Sim. On YouTube there is a gentleman (amstudio) who has used motors on the Gas and Brake pedals to give some realism to the Sim. To achieve this he used a Uno 3 and a motor shield. The motors used are those that you'd find in the XBox/PS4 controllers. It's my understanding that the Uno 3, Nano and Micro are the same in its basic form, meaning that the sketch he uses can be used on all 3. If this is true then I want to use the smallest footprint to achieve the Rumble effect.

**Question** is how do I wire up the Nano to do this and with the motors as small as they are is it really necessary to have a motor shield or H bridges?

I have taken a picture of his Uno setup.  My aim here is to make it the smallest as it can be and still do the function of this mod' as this will be its only function. Any ideas on how best to go about this, The XBox Controller is rated at 5v @ 450mA. have included a picture showing his setup.thanks in advance![![enter image description here][1]][1]

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

title: how to use Nano instead of Uno3 to operate DC motors

Answers: 1

body:
> It's my understanding that the Uno 3, Nano and Micro are the same in its basic form

Not exactly. The Uno and Nano use the same chip (the Atmega328p) and have the same pins broken out. The Arduino Pro Mini also uses that chip, but I think the pinout is a bit different. But mostly a code can be reused between these boards. The Arduino Micro uses an ATmega32U4, which is a different chip. Depending on the actual code, you might not be able to just reuse the code. Then you might have to change to code to use the Micros hardware.

> with the motors as small as they are is it really necessary to have a motor shield or H bridges?

I would say yes. A digital output pin of an Arduino can only supply 20mA of current over longer time (absolute maximum 40mA). Even very small motors can easily exceed that. As long as you don't know the exact needed current in worst case (like stalling the motor), you should assume, that it is more than 20mA. Also a running motor generates a lot of electrical noise and the coils can induce backcurrents, that might destroy the output hardware of the Arduino pin (for that you need a flyback diode). And lastly, if you want to change the direction of the motor, you absolutely need an H-bridge. Otherwise it is only on or off.

> Question is how do I wire up the Nano to do this

With H-bridges you normally need 3 pins to control the motor:

- The enable pin (often marked as EN) enables or disables the motor (run or stop). You normally use `analogWrite(en_pin, speed)` to control the speed of the motor. It will send a PWM signal with the given duty cycle to the enable pin.
- And you have 2 input pins (often marked as IN). They give you control over the direction.
    - `IN1` to HIGH and `IN2` to LOW will give you the first direction. Reversing to `IN1` LOW and `IN2` HIGH will give you the other direction. This will cause the H-bridge to lead the current through the motor in different directions.
    - Setting them to the same value will cause the motor to break (because that will short circuit the motors coil).

So you would wire 3 output pins of the Arduino to the mentioned pins on the H-bridge. It is up to you, what you want to use here. You can use a shield (which is normally the size of the Uno), you can use other ready to use motor driver boards (there are many) or you could build your own driver with a H-bridge chip and flyback diode.


body:
I'm working on a driver for an SPI device that returns some data (device status) while the command byte is still being written.  Is there a way to read this status data using standard Arduino APIs or do I need to bit-bang to access it?

Here's what the SPI signals look like:

[![SPI timing diagram][1]][1]

The 6 bits in red are the ones I'm interested in reading.

---

For context, the device in question is a Microchip [MCP3561 ADC](https://ww1.microchip.com/downloads/en/DeviceDoc/MCP3561-2-4-Two-Four-Eight-Channel-153.6-ksps-Low-Noise-24-Bit-Delta-Sigma-ADCs-DS20006181B.pdf) (MCP3X6X series).  [It has a bug](https://ww1.microchip.com/downloads/en/DeviceDoc/MCP3X5X-Family-Data-Sheet-Errata-DS80000845B.pdf) (erratum 2) where the new-data-ready flag (`/DR_STATUS`) is not always set correctly.  Part of the work-around involves reading the status bits mentioned above.

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

title: SPI read while writing?

Answers: 1

body:
[The `SPI.transfer()` method][spi] is designed to send a byte through
the SPI port and, _at the same time_ receive an incoming byte.

Usage pattern:

```c++
uint8_t byte_to_send = ...;
uint8_t received_byte = SPI.transfer(byte_to_send);
```

[spi]: https://www.arduino.cc/en/Reference/SPITransfer


body:
I was working on a program to measure the pulse width , for that I thought of using Timer 2 in Arduino mega along with pin change interrupt,

The program I have written is as follows

```
volatile float ovfCount = 0;

typedef struct{
  float curr_ovfCount,prev_ovfCount;
  uint8_t curr_tcnt2, prev_tcnt2;
  uint16_t width;
  bool stateHigh = true;
}Pulse;

Pulse ch1, ch2, ch3, ch4, ch5, ch6;

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

  /*
   * Pin Change Interupt for
   * measuring the pulse width
   * from the receiver
   *
   */

  DDRK = 0; // A8:A15 -> direction as Input
  PORTK = B00111111; // A8:A15 -> pullupResistor

  PCICR = B00000100; // activating 2 nd PCINT
  PCIFR = 0; // resetting the flags
  PCMSK2 = B00111111; // activating from A8:21 :: 6

  /*
   * 8 bit timer setup for counting
   * timer 2 is used
   */
   TCCR2B=0x00;
   TCCR2A = 0x00; // wave generation is normal:: all zeros
   TCNT2 = 0x00;
   TIFR2 = 0x00; // resetting all flags
   TIMSK2 = 0x01; //timer overflow enable
   TCCR2B = 0x01; // no prescaling

}

ISR(TIMER2_OVF_vect){
  ovfCount++;
}

ISR(PCINT2_vect){
  float ovf_count = ovfCount;
  uint8_t tcnt2 = TCNT2;

  if( (PINK & 1 << PINK0) & ch1.stateHigh ){
    //Low-High
    ch1.prev_ovfCount = ovf_count;
    ch1.prev_tcnt2 = tcnt2;
    ch1.stateHigh = false;
  } else if( ! ((PINK & 1 << PINK0) & ch1.stateHigh)){
//    High-Low
    ch1.curr_ovfCount = ovf_count;
    ch1.curr_tcnt2 = tcnt2;
    ch1.width = (256.0*(ch1.curr_ovfCount - ch1.prev_ovfCount) + (ch1.curr_tcnt2 - ch1.prev_tcnt2) ) * 1000 / 16e6;
    ch1.stateHigh = true;
  }

}

void loop() {
  Serial.println(ch1.width);
  pinMode(13, OUTPUT);
  digitalWrite(13,!digitalRead(13));
  delay(1000);

}

```

and the output I am getting is ,

```
16:22:05.667 -> 0
16:22:05.847 -> 927
16:22:06.826 -> 927
16:22:07.820 -> 1001
16:22:08.847 -> 1001
16:22:09.837 -> 1001
16:22:10.843 -> 1001
16:22:11.835 -> 1002
16:22:12.863 -> 1002
16:22:13.871 -> 1002
16:22:14.854 -> 1002
16:22:15.873 -> 1003
16:22:16.875 -> 1003
16:22:17.887 -> 1003
16:22:18.860 -> 1003
16:22:19.875 -> 1003
16:22:20.867 -> 1003
16:22:21.907 -> 1003
16:22:22.895 -> 1003
16:22:23.922 -> 1008
16:22:24.921 -> 1008
16:22:25.938 -> 1008
16:22:26.922 -> 1008
16:22:27.939 -> 1008
16:22:28.961 -> 1008
16:22:29.946 -> 1008
16:22:30.971 -> 1008
16:22:31.993 -> 1008
16:22:32.974 -> 1008
16:22:34.011 -> 1008
16:22:35.016 -> 1008
16:22:36.026 -> 1008
16:22:37.012 -> 1008
16:22:38.024 -> 1008
16:22:38.939 -> 1008
16:22:39.802 -> 906
16:22:40.638 -> 906
16:22:41.508 -> 844
16:22:42.345 -> 844
16:22:43.189 -> 842
16:22:44.059 -> 842
16:22:44.905 -> 843
16:22:45.750 -> 843
16:22:46.593 -> 842
16:22:47.428 -> 842
16:22:48.305 -> 842
16:22:49.139 -> 842
16:22:50.011 -> 845
16:22:50.839 -> 845
16:22:51.707 -> 842
16:22:52.539 -> 842
16:22:53.419 -> 842
16:22:54.260 -> 842
16:22:55.111 -> 842
16:22:55.975 -> 842
16:22:56.791 -> 842
16:22:57.642 -> 842
16:22:58.492 -> 842
16:22:59.372 -> 842
16:23:00.212 -> 842
16:23:01.046 -> 842
16:23:01.918 -> 842
16:23:02.775 -> 842
16:23:03.600 -> 849
16:23:04.473 -> 849
16:23:05.329 -> 842
16:23:06.159 -> 842
16:23:07.022 -> 842
16:23:07.862 -> 842
16:23:08.709 -> 842
16:23:09.574 -> 842
16:23:10.412 -> 843
16:23:11.292 -> 843
16:23:12.116 -> 848
16:23:12.996 -> 848
16:23:13.899 -> 848
16:23:14.779 -> 848

```

The output I am expecting is 1000 as the connection to the PCINT is directly form the digital pin13 of the Arduino and it is made to blink at that interval

I want to know

 - What mistake I am making here in measuring the counts
 - How can I generalise this method for measuring width of 6 channels simultaneously.

===== Edit after input from Edgar Bonet ===========

I have written a program , can you please tell me is this a good way to accomplish my requirement

```
volatile uint32_t ovfCount = 0;

struct Pulse {
  uint32_t last_toggle;
  uint32_t width;
  bool stateHigh;
  bool input_is_high;
  uint32_t get_width() {
    noInterrupts();
    uint32_t width_copy = width;
    interrupts();
    return width_copy;
  }
};

Pulse ch1, ch2, ch3, ch4, ch5, ch6;

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

  /*
     Pin Change Interupt for
     measuring the pulse width
     from the receiver

  */

  DDRK = 0; // A8:A15 -> direction as Input
  PORTK = B00111111; // A8:A15 -> pullupResistor

  PCIFR = 0; // resetting the flags
  PCMSK2 = B00111111; // activating from A8:21 :: 6
  PCICR = B00000100; // activating 2 nd PCINT

  /*
     8 bit timer setup for counting
     timer 2 is used
  */
  TCCR2B = 0x00;
  TCCR2A = 0x00; // wave generation is normal:: all zeros
  TCNT2 = 0x00;
  TIFR2 = 0x00; // resetting all flags
  TIMSK2 = 0x01; //timer overflow enable
  TCCR2B = 0x01; // no prescaling

  DDRH = B00111000;
  fastPWM_init();

}

void fastPWM_init() {
  //    clearing
  TCCR4A = 0; TCCR4B = 0; TCCR4C = 0;
  //    Initializing
  TCCR4A = B10101010; // OC4A, OC4B, OC4C : ICR-WGM
  TCCR4B = B00011010; // ICR-WGM prescalar : 8
  //    Setting frequency
  ICR4 = 39999;
  //    Setting PWM
  OCR4A = 2000; OCR4B = 2000; OCR4C = 2000;
}

ISR(TIMER2_OVF_vect) {
  ovfCount++;
}

ISR(PCINT2_vect) {
  uint8_t tcnt2 = TCNT2;
  uint32_t ovf_count = ovfCount;

  if ( bit_is_set(TIFR2, TOV2) && tcnt2 < 128 ) {
    ovf_count ++;
  }

  uint32_t time = ovf_count << 8 | tcnt2;

  pinChangeFunction(&ch1, time, PK0);
  pinChangeFunction(&ch2, time, PK1);
  pinChangeFunction(&ch3, time, PK2);
  pinChangeFunction(&ch4, time, PK3);
  pinChangeFunction(&ch5, time, PK4);
  pinChangeFunction(&ch6, time, PK5);

}

void pinChangeFunction(Pulse *channel, uint32_t time, uint8_t pin){
  channel->input_is_high = bit_is_set(PINK, pin);
  if (channel->input_is_high && !channel->stateHigh) {
    channel->stateHigh = true;
  } else if (! channel->input_is_high && channel->stateHigh) {
    channel->width = time - channel->last_toggle;
    channel->stateHigh = false;
  }
  channel->last_toggle = time;
}

void loop() {

  if(Serial.available() > 0){
    OCR4A = Serial.parseInt();
  }

  Serial.print(ch1.get_width() / 16e3);Serial.print("\t");
  Serial.println(ch6.get_width() / 16e3);

}

```

The PWM is only used for testing.

title: Issue using Arduino Mega Timer2 with PinChange Interrupt

Answers: 1

body:
There are quite a few issues with this program. The most obvious is the
use of floating point calculations in interrupt context. Interrupts
should be served as fast as possible, and floating point is really slow
on the AVR.

Some other issues:

* Interrupt flags should be cleared by writing a logic 1 to them,
  however silly it may sound.

* A couple if `&` operators in `ISR(PCINT2_vect)` are probably meant to
  be `&&`.

* The logic for detecting rising and falling edges is all wrong.

* There is no need to store so much data in the `Pulse` objects.

* `ch1.width` should be read with interrupts disabled in order to avoid
  a data race.

* There is a subtle race condition when reading `ovfCount` and `TCNT2`:
  if the timer overflows right when `ISR(PCINT2_vect)` starts running,
  that overflow will not be counted.

Here is a version of the program that attempts to fix all these points.
I also changed it for running on an Uno (with pin 13 = `PB5` =
`PCINT5`), so that I could test it:

```c++
/*
 * Pulse width via PCINT.
 *
 * https://arduino.stackexchange.com/questions/81688
 */

volatile uint32_t ovfCount = 0;

struct Pulse {
    uint32_t last_toggle;
    uint32_t width;
    bool stateHigh;
    uint32_t get_width() {
        noInterrupts();
        uint32_t width_copy = width;
        interrupts();
        return width_copy;
    }
};

Pulse ch1, ch2, ch3, ch4, ch5, ch6;

void setup() {
    Serial.begin(115200);
    pinMode(13, OUTPUT);

    /* Setup Pin Change Interrupt for detecting pulses. */
    PCMSK0 = _BV(PCINT5);  // sense change on pin 13 = PB5 = PCINT5
    PCIFR  = _BV(PCIF0);   // reset interrupt flag
    PCICR  = _BV(PCIE0);   // enable PCINT0_vect: pins PCINT[7:0]

    /* Setup Timer 2 for counting. */
    TCCR2B = 0;           // stop
    TCCR2A = 0;           // normal mode
    TCNT2  = 0;           // reset timer
    TIFR2  = _BV(TOV2);   // reset interrupt flag
    TIMSK2 = _BV(TOIE2);  // enable timer overflow interrupt
    TCCR2B = _BV(CS20);   // count at F_CPU/1
}

ISR(TIMER2_OVF_vect) {
    ovfCount++;
}

ISR(PCINT0_vect) {
    uint8_t tcnt2 = TCNT2;
    uint32_t ovf_count = ovfCount;

    // Was there an overflow that has not yet been accounted for?
    if (bit_is_set(TIFR2, TOV2) && tcnt2 < 128) {
        ovf_count++;
    }

    uint32_t time = ovf_count << 8 | tcnt2;

    bool input_is_high = bit_is_set(PINB, PB5);
    if (input_is_high && !ch1.stateHigh) {  // low -> high
        ch1.stateHigh = true;
    } else if (!input_is_high && ch1.stateHigh) {  // high -> low
        ch1.width = time - ch1.last_toggle;
        ch1.stateHigh = false;
    }
    ch1.last_toggle = time;
}

void loop() {
    digitalWrite(13, HIGH);
    delay(1000);
    digitalWrite(13, LOW);
    delay(200);
    Serial.println(ch1.get_width() / 16e3, 5);
}
```

And here is the output:

```text
1000.02349
1000.01959
1000.01916
1000.02496
1000.01959
1000.02032
1000.01947
1000.02795
1000.02642
1000.01855
1000.01916
1000.02105
1000.02490
1000.01782
1000.03033
1000.01898
...
```

The printed values are larger than 1000 because of the time needed to
execute `digitalWrite()`.

Also note that an 8-bit timer running at the full CPU speed overflows
every 16 µs. That's quite a lot of pressure on the CPU, and many
operations will take longer that expected because of these interrupts.
If I wanted to time something with single-cycle resolution, I would
reach for a 16-bit timer. And I would prefer using input capture,
although sadly only two input capture channels are available on the Mega
(on pins 48 and 49).

------------------------------------------------------------------------

**Edit**: Answering the questions in the comments.

> please have a look at my question edits and please advice.

I did not test it, but it seems to me this code should work. I would
prefer, however, having a different interrupt for each channel.
Otherwise, the successive calls to `pinChangeFunction()` can make the
execution of this ISR quite long.

Also note that `Pulse::input_is_high` serves no useful purpose. Storing
this value in the object slows down the ISR, as it has to access memory,
whereas a local variable would be kept in a (much faster) internal CPU
register.

> what will we do if we have 8 channels as in the radio receiver?

You could use 6 external interrupts and 2 pin change
interrupts.

> Why did you take `tcnt2 < 128` when `tcnt2` max is 256?

This one is tricky. I'll try to explain the whole logic of the test.

Consider the following naive version of the ISR:

```c++
ISR(PCINT0_vect) {
    // ← A
    uint8_t tcnt2 = TCNT2;
    uint32_t ovf_count = ovfCount;
    uint32_t time = ovf_count << 8 | tcnt2;
    // ...
}
```

There is a small chance that Timer 2 overflows at point A, i.e.
while this ISR is executing its prologue and has not yet read `TCNT2`.
If this happens, the `TIMER2_OVF` ISR will not run immediately, because
we are already executing an ISR, and ISRs do not nest. Then, `ovfCount`
is not updated. If this happens, we then read a value of `TCNT2`
affected by the overflow, and a value of `ovfCount` that does not
account for that overflow. We then combine together those inconsistent
values into a `time` value that misses 256 timer ticks.

We can detect this situation by reading the `TOV2` flag in `TIFR2`. This
flag is set only when there is a pending interrupt request for
`TIMER2_OVF`, i.e. if the counter has overflowed and that overflow has
not yet been accounted for in `ovfCount`. Thus the “fixed” ISR looks
like this:

```c++
ISR(PCINT0_vect) {
    // ← A
    uint8_t tcnt2 = TCNT2;
    // ← B
    uint32_t ovf_count = ovfCount;
    // ← B
    if (bit_is_set(TIFR2, TOV2)) {
        ovf_count++;
    }
    uint32_t time = ovf_count << 8 | tcnt2;
    // ...
}
```

With this, if the overflow happens at point A, we manage to compute the
proper `time`. But consider now what would happen if the timer overflows
at either of the points marked B, i.e. after reading `TCNT2` but before
reading `TOV2`. If this happens, we read the pre-interrupt values of
both `TCNT2` and `ovfCount`. No correction is thus needed for computing
a consistent `time`. Yet, `TOV2` is raised when we test it: we then
apply an unneeded correction, and we end up with a `time` that is too
large by 256 ticks.

In order to fix this problem, we have to make sure the correction is
applied if the overflow happens at point A, but not if it happens at
point B. How can we tell apart those two situations? The answer is: by
looking at the value recorded in `tcnt2`. In case A, the counter was
read right after the overflow, so it had a very small value (close
to 0) when it was copied to `tcnt2`. In case B, the counter was
read when it was just about to reach the overflow, so it had a very
large value (close to 255). If `TOV2` is set when we read it, this
means an overflow happened during the very beginning of the current ISR,
very close to the point where we read `TCNT2`. So the value recorded in
`tcnt2` has to be either very small or very large. It cannot be in the
middle (close to 128).

So we have to decide whether `tcnt2` is very small or very large. There
are many possible values that could be used as a threshold. The most
natural is the mid range: 128. It is also the most efficient to compute,
as the compiler can optimize the comparison into a simple test of the
most significant bit. Thus the final version of the test:

```c++
    if (bit_is_set(TIFR2, TOV2) && tcnt2 < 128) {
        ovf_count++;
    }
```


body:
While using a 3.3v Pro Mini & Wemos mini to communicate via Serial was successful, when tried with a 5v Pro Micro it fails.

To overcome different logic level I used a 10K + 20K resistors to lower Pro-Micro's 5v to 3.3v successfully to `Tx` and `Rx` pins. Also since they are on the same PCB, `GND` pins are connected and `RAW` to `5V` at wemos mini  is also connected. At the moment, it is powered up using MCU's USB input ( tried to connect to Pro-Micro only, Wemos Only, and both ).

[![Schematics][1]][1]
What might be the problem ?

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

title: Wemos Mini & Pro Micro Serial connection

Answers: 1

body:
You don't need a logic level conversion between 5 V Micro Arduino and 3.3 V Wemos D1 mini. The 5 V ATmega 328p reads 3.3 V as HIGH and the esp8266 can tolerate 5 V logic level for tests. For long term connection you can add logic level conversion with a voltage divider to convert the 5 V of ATmega TX to 3.3 V of esp8266 RX.

RX/TX pins on Arduino Mini are Serial.
RX/TX pins on Arduino Micro are **Serial1**.
Serial is only USB on Micro.


body:
I've been trying to use this HC-05 bluetooth module for a project, where the data would be sent to a Max/MSP/jitter program. Initially, every time I connected my bluetooth device to my computer, it stayed connected for about 10 to 20 seconds then disconnect. I'm not sure if it's a voltage thing, but from what I read on other forums, it should work fine. My setup:

1- Powering Arduino on a wall wart (Input: 100-240V AC, 50/60Hz 0.3A ; Output: 12V DC 1A);

2- Bluetooth's Tx to Arduino's Rx (D3) and Bluetooth's Rx to Arduino's Tx (D4)

3- APDS9960 sensor also connected on the same breadboard (the sensor I should be receiving the data from, and I do, when connected on an USB cable port)

4 - HC-05 configured to be 115200 baud (AT+UART=115200,0,0), which seems to be the appropriate bps for HC-05 to Max (??)

But then... Once I logged into Max, and printed the data from this serial port (which should send data in a continuous fashion), some lines were printed and then it stopped. So I go on to check the Arduino Serial Monitor and – though everything seemed to be working fine and I received the data properly – there's nothing showing up.

    #include "SoftwareSerial.h"
    #include <Arduino_APDS9960.h>

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

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

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

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

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

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

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

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

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

title: Not Receiving HC-05 data

Answers: 0