# Question
Title: Arduino does not boot when SPI lines are loaded
i connected an Arduino Nano to an external SPI Flash using THIS tutorial (russian) and the SPIMemory library. While accessing the Flash works well, i have encountered the following issue:

**The Problem: When the SPI MISO line is pulled high by the flash while the Arduino boots, it does not start**, for example because it was rebooted while accessing the flash. I have to power down the Flash before it boots again. But even then, it takes unusually long to boot.

I know that the Atmega328p allows reprogramming via SPI, but to my knowledge this should not cause this behavior since the SPI lines do not change (starting the programming mode would require a command to be sent immediately after restart). Is there any way to prevent this behavior? (Except disabling SPI programming via fuse bits, this would be my last choice)

**EDIT**

Programming the Arduino via ISP does work, however i added some series resistors to the flash to prevent accidentally driving the SPI lines from multiple sources.

The problem seems to come from the MISO line, when it is pulled to VCC the Arduino does not start. This is not mentioned in the data sheets anywhere and i am not sure how to prevent this (sketch below to show the wiring).

# Answer
I honestly can't imagine why a sketch like that would hang in this scenario. But I'm confident that my answer can solve the issue.

My guess is that the following happens: The flash is selected (CS pulled low by atmega) at the moment at which the reset happens. At this moment, the master will stop generating a clock signal and CS will be floating. Thus, the flash will not be deselected *reliably* due to the floating CS and MISO will remain in the state it was before the reset occured (HIGH if it was transmitting a logic 1, LOW for 0). Basically, the SPI communication of the flash will be stuck with MISO being actively pulled to logic high or low.

IDK why this causes the sketch to freeze, but if you add a pullup resistor to the flash's CS, it should be deactivated by default (and also after a reset of the atmega as pins will be inputs/floating by default). As a result, the flash can not actively pull MISO and should therefore barely affect the atmega at all.

I suggest you add the mentioned pullup and see if that makes any difference. If it doesn't I'm going to delete this answer, but it was a bit too long for a comment ;).

Edit: I also just saw that you are missing the pullup resistor on the reset pin. That could well be the actual problem.
> 1 votes

---
Tags: arduino-nano, spi, flash
---


# Question
Title: How to reset a variable just before entering a function?
I am facing a problem where the if condition in the function `waterNowrun` is able to execute once after the program starts as the variable `v` is 0 at the start, but upon starting it again the if does not execute as `v` is not \<10.

After some debugging I had decided that `v` would have to be reset before entering the function, and so I set `v` to 0 in the loop, then what happened is that the if was always satisfied and did not go to the else.

Is it possible to do it? Maybe with interrupts or something else?

Hardware-ESP8266 based NodeMCU

**In conclusion-**

I want a reset a variable `v` once just before the function `waterNowrun` starts, how do I do it?

**My code-**

```
#include <ESP8266WiFi.h>
#include <BlynkSimpleEsp8266.h>
#include <NTPClient.h>
#include <WiFiUdp.h>
#include "DHT.h"
#include "LiquidCrystal_PCF8574.h"

#define BLYNK_PRINT Serial
#define DHT_PIN_DATA  12
// LCD definations
#define LCD_ADDRESS 0x27
#define LCD_ROWS 2
#define LCD_COLUMNS 16
#define SCROLL_DELAY 150
#define BACKLIGHT 25
#define DHTTYPE DHT22

// You should get Auth Token in the Blynk App.
// Go to the Project Settings (nut icon).
char auth[] = "ymri80lFL9_xZhf6WIRHtQ1qadfafdEWOt9zBy";
char ssid[] = "-Hotspot-82DB";
char pass[] = "b35288qqafdd";
int autoSch;
int waterNow;
int morTime;
int afterTime;
int postNoon;
int eveTime;
int schTime;
int minStep;
int interval;
int count;
int flag = 0;
int soilHum = A0;
int v;
unsigned long previousMillis = 0;

DHT dht(DHT_PIN_DATA, DHTTYPE);
LiquidCrystal_PCF8574 lcdI2C;
WiFiUDP ntpUDP;
NTPClient timeClient(ntpUDP, "in.pool.ntp.org", 19800, 600000);
// This function will be called every time Slider Widget
// in Blynk app writes values to the Virtual Pin 1

BLYNK_CONNECTED() {
  Blynk.syncAll();
}

BLYNK_WRITE(V0)
{
  autoSch = param.asInt(); // assigning incoming value from pin V1 to a variable
}

BLYNK_WRITE(V1)
{
  morTime = param.asInt(); // assigning incoming value from pin V1 to a variable
}

BLYNK_WRITE(V2)
{
  afterTime = param.asInt(); // assigning incoming value from pin V1 to a variable
}

BLYNK_WRITE(V6)
{
  postNoon = param.asInt(); // assigning incoming value from pin V1 to a variable
}

BLYNK_WRITE(V3)
{
  eveTime = param.asInt(); // assigning incoming value from pin V1 to a variable
}

BLYNK_WRITE(V10)
{
  waterNow = param.asInt(); // assigning incoming value from pin V1 to a variable
Serial.println("Boo BOO is BOO BOO billa");
}

BLYNK_WRITE(V4)
{
  schTime = param.asInt(); // assigning incoming value from pin V1 to a variable
}

BLYNK_WRITE(V7)
{
  minStep = param.asInt(); // assigning incoming value from pin V1 to a variable
}

void setup()
{
  dht.begin();
  lcdI2C.begin(LCD_COLUMNS, LCD_ROWS, LCD_ADDRESS, BACKLIGHT);
  pinMode(LED_BUILTIN, OUTPUT);
  digitalWrite(LED_BUILTIN, HIGH);
  pinMode(14, OUTPUT);
  digitalWrite(14, LOW);
  Blynk.virtualWrite(V5, 0);
  Blynk.virtualWrite(V8, 0);
  pinMode(0, INPUT_PULLUP);
  Serial.begin(9600);

  //WiFi.begin(ssid, password);
  Blynk.begin(auth, ssid, pass);
  while ( WiFi.status() != WL_CONNECTED ) {
    delay ( 500 );
    Serial.print ( "." );
  }
  timeClient.begin();
  Blynk.syncAll();
}

void loop()
{
  Blynk.run();
  time_run();
  lcd();
  butPress();

  timeClient.update();
  if (waterNow != 1) {
    Blynk.virtualWrite(V10, 0);
   // digitalWrite(14, LOW);
    Blynk.virtualWrite(V5, 0);
    Blynk.virtualWrite(V8, minStep * 60);

    Blynk.syncAll();
  }
  if (waterNow == 1) {
    waterNowrun(v = 0);

  } else if (autoSch == 0) {
    auto_run1();
  } else if (autoSch == 1) {
    sch_run2();
  } else {
    Blynk.virtualWrite(V10, 0);
    digitalWrite(14, LOW);
    Blynk.virtualWrite(V5, 0);
    Blynk.syncAll();
  }
  Blynk.syncAll();
  Serial.println(timeClient.getFormattedTime());
  Serial.println(analogRead(A0));
}
void butPress() {
  if (digitalRead(0) == LOW) {
    if (flag == 0) {

      digitalWrite(14, HIGH);
      delay(3000);
      digitalWrite(14, LOW);

      flag = 1;
    }
    else {
      digitalWrite(14, LOW);
      flag = 0;
    }
  }
}

void test() {
  if (v < 10) {
    digitalWrite(14, HIGH);
    v++;
    delay(500);

  } else {
    digitalWrite(14, LOW);

  }

}

void lcd() {
  //lcdI2C.clear();
  lcdI2C.setCursor(0, 0);
  timeClient.update();
  lcdI2C.print(timeClient.getFormattedTime());

  if (autoSch == 0) {
    lcdI2C.setCursor(9, 0);
    lcdI2C.print("Auto     ");
  } else {
    lcdI2C.print(" Sch   ");
  }

  if (digitalRead(14) == 1) {
    lcdI2C.selectLine(2);
    lcdI2C.print("Wtr Now           ");
  }
  else
  {

    if (int(timeClient.getHours()) < 6 && morTime == 1 && autoSch == 0) {
      Blynk.syncAll();
      lcdI2C.selectLine(2);
      lcdI2C.print("Auto Wtr at: 6a ");
    } else if (int(timeClient.getHours()) < 12 && afterTime == 1 && autoSch == 0) {
      Blynk.syncAll();
      lcdI2C.selectLine(2);
      lcdI2C.print("Auto Wtr at: 12n ");
    } else if (int(timeClient.getHours()) < 14 && postNoon == 1 && autoSch == 0) {
      Blynk.syncAll();
      lcdI2C.selectLine(2);
      lcdI2C.print("Auto Wtr at:14pn ");
    } else if (int(timeClient.getHours()) < 18 && eveTime == 1 && autoSch == 0) {
      Blynk.syncAll();
      lcdI2C.selectLine(2);
      lcdI2C.print("Auto Wtr at: 18e ");
    } else if (int(timeClient.getHours()) >= 18 && morTime == 1 && autoSch == 0) {
      Blynk.syncAll();
      lcdI2C.selectLine(2);
      lcdI2C.print("Auto Wtr at: 6a ");
    } else {
      lcdI2C.selectLine(2);
      lcdI2C.print("My name is billa");
    }

  }

}

void waterNowrun(int v) {
  /*
    Serial.println (currentMillis);
    Serial.println (previousMillis);
    Serial.println(interval);
  */

  if (v < 10) {

    Serial.println("Boo Boo");

    digitalWrite(14, HIGH);
    Blynk.virtualWrite(V5, 255);
    lcdI2C.selectLine(2);
    lcdI2C.print("Wtr Now :");
    /*
      lcdI2C.print((minStep * 60) - ((currentMillis - previousMillis) / 1000));
      Blynk.virtualWrite(V8, ((interval / 1000) - ((currentMillis - previousMillis) / 1000)));
    */
    Blynk.syncAll();
    delay(500);
    v++;
  } else {
    Blynk.virtualWrite(V10, 0);
    digitalWrite(14, LOW);
    Blynk.virtualWrite(V5, 0);
    Blynk.virtualWrite(V8, 0);

    Blynk.syncAll();

  }
}

void sch_run2() {
  if (schTime == 1) {
    digitalWrite(14, HIGH);
    Blynk.virtualWrite(V5, 255);
    Blynk.syncAll();
  } else if (schTime == 0) {
    digitalWrite(14, LOW);
    Blynk.virtualWrite(V5, 0);
    Blynk.syncAll();
  }

}

void time_run() {
  Blynk.virtualWrite(V11, int(timeClient.getHours()));
  Blynk.virtualWrite(V12, int(timeClient.getMinutes()));
  Blynk.virtualWrite(V13, float(dht.readTempC()));
  Blynk.virtualWrite(V14, float(dht.readHumidity()));

}

void auto_run1() {
  if (morTime == 1 && String(timeClient.getFormattedTime()) > "06:00:00" && String(timeClient.getFormattedTime()) < "06:20:00") {
    digitalWrite(14, HIGH);
    Blynk.virtualWrite(V5, 255);
    Blynk.syncAll();
  }
  else if (afterTime == 1 && String(timeClient.getFormattedTime()) > "12:00:00" && String(timeClient.getFormattedTime()) < "12:20:00") {
    digitalWrite(14, HIGH);
    Blynk.virtualWrite(V5, 255);
    Blynk.syncAll();
  }
  else if (postNoon == 1 && String(timeClient.getFormattedTime()) > "14:00:00" && String(timeClient.getFormattedTime()) < "14:20:00") {
    digitalWrite(14, HIGH);
    Blynk.virtualWrite(V5, 255);
    Blynk.syncAll();
  }
  else if (eveTime == 1 && String(timeClient.getFormattedTime()) > "12:59:00" && String(timeClient.getFormattedTime()) < "13:01:00") {
    digitalWrite(14, HIGH);
    Blynk.virtualWrite(V5, 255);
    Blynk.syncAll();
  }
  else  {
    //(String(timeClient.getFormattedTime() == "06:20:00" || "12:20:00" || "14:20:00" || "13:48:00"))
    //waterNowrun();
    /*
      Blynk.virtualWrite(V10, 0);
      digitalWrite(14, LOW);
      Blynk.virtualWrite(V5, 0);
      Blynk.virtualWrite(V8, 0);
      Blynk.syncAll();
    */
  }
}

```

# Answer
> 3 votes
The purpose of the waterNowrun function and 'v' seems to be to turn on some water and keep it running for 10 iterations, before turning it off?

I would split the waterNowrun into two functions:

```
void waterOn() {
    Serial.println("Boo Boo");
    digitalWrite(14, HIGH);
    Blynk.virtualWrite(V5, 255);
    lcdI2C.selectLine(2);
    lcdI2C.print("Wtr Now :");
    /*
      lcdI2C.print((minStep * 60) - ((currentMillis - previousMillis) / 1000));
      Blynk.virtualWrite(V8, ((interval / 1000) - ((currentMillis -     previousMillis) / 1000)));
    */
    Blynk.syncAll();
    delay(500);
}

void waterOff() {
    Blynk.virtualWrite(V10, 0);
    digitalWrite(14, LOW);
    Blynk.virtualWrite(V5, 0);
    Blynk.virtualWrite(V8, 0);
    Blynk.syncAll();
}

```

In the loop() I would do

```
...
if (waterNow != 1) {
    waterOff();
}
if (waterNow == 1) {
    if (v < 10) {
        waterOn();
        v++;
    }
    else {
        waterOff();
        v = 0;
    }
} else if (autoSch == 0) {
    auto_run1();
} else if (autoSch == 1) {
    sch_run2();
} else {
    waterOff();
}
...

```

But do yourself a favour and rename v to waterPeriod or something that is easier to remember.

# Answer
> 0 votes
It isn't clear what behavior you expect from `v`, especially since you have two of them - the global `v` at the head of your program, and the parameter `v` of the function `waterNowrun(int v)`.

My understanding of what you want is that the function should maintain control of `v`. If so,

* Get rid of the global `v`';
* In `loop()`, don't pass anything to `waterNowrun()`
* Inside `waterNowrun()` declare `static int v = 0;`. That initialization to zero will only happen once, before the program starts (not on every entry to the function, even though it kind of reads like that). From then on, only your `waterNowrun()` function can change `v`.

That may not be the only logic change you need to make - I don't understand what you're trying to do with `v` and can't critique that. But at least now `v` will be entirely controlled from within the function, and it will not change between invocations of the function.

Some background: A static variable declared within a function is like a global in that it has a fixed memory address for the entire program run; unlike a local (including a function parameter) that gets reallocated in memory each time the function is entered (and therefore must be initialized on every entry). But *unlike* a global, it is invisible - not known about - anywhere outside of that function.

---
Tags: variables, functions
---


# Question
Title: Is it possible to extract the firmware of an Arduino BLE or IoT board wirelessly?
I've looked at previous questions regarding sketch extraction and know that it is possible to extract the hex code from an Arduino board using avrdude from the command line.

However, I want to see if the following is possible:

1. Connect to Arduino 33 IoT board
2. Extract onboard Firmware as a hex file
3. Disconnect from Arduino 33 IoT board.

I understand that getting the initial source code is not possible, but I am in particular looking to just get the hex code in a wireless manner. If it is not possible via the Arduino 33 IoT board, is there any Arduino board with which this can be done? Any help or guidance would be appreciated.

# Answer
Technically, the firmware can read its own application section, but it won't send it to you wirelessly (or via any interface) if such a feature isn't implemented in that firmware. If you were to implement the firmware yourself, you can do (almost) anything. But if it is a third party firmware, this will not be possible.

The reason this works with arduinos and avrdude is, because firmware up- and download are implemented in hardware (ISP, works without a bootloader).
> 1 votes

---
Tags: wireless, firmware, arduino-nano-ble, arduino-nano-33-iot
---


title: WiFi Password Safety

text:
# Question
Title: WiFi Password Safety
Are there any best practices regarding password safety? The following is taken from a wifi tutorial sketch.

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

char ssid[] = "yourNetwork";      // your network SSID (name)
char pass[] = "secretPassword";   // your network password
int keyIndex = 0;                 // your network key Index number (needed only for WEP)

```

While I accept that the tutorial is there for learning how to use the shield, I would assume hard coding the password into the sketch leaves this open to attackers. Is this actually the case? If so, are there any strategies to harden the sketch, for example with encrypted storage?

I am a relative newbie with physical computing and Arduino, so sorry if I am overlooking something obvious.

# Answer
> 12 votes
You're actually entering into a very tricky and difficult area.

Yes, having a plain text password in your sketch is a risk. It is stored in flash as plain text. If an attacker can gain access to the contents of the flash through some means (whatever they may be) then they could obtain that WiFi password.

You would think that encrypting the password would be the answer, but that's not the case. The problem with an encrypted password like this is it has to be decrypted to use it. That means that both the encrypted password and the encryption key are both stored together in flash. If you can get one you can get the other, and thus the encryption is null and void. Encryption security relies on keeping the encrypted data and the key used to encrypt/decrypt it completely separate. After all, you don't leave the key to your house in the front door lock when you go out, do you? It's exactly the same.

So what do you do?

Well, there's lots of different ways of looking at security. In this case there is one specific viewpoint that works best:

# Security Through Obscurity

Your system is (pretty much) unique. Nobody but you knows just what it does and how it does it, or how you interact with it. It's not obvious to the casual observer just what it is or what could be done with it. That means that they won't know how to break in to it.

The majority of use of vulnerabilities in systems rely on those systems being ubiquitous - that is, all over the place; easy to obtain. In short, easy to find out what they are, how they work, and even reverse engineer them to a certain extent. Attackers aren't going to be able to do that with your system, since you are the only person in the world with it.

However, it's far from perfect, and you shouldn't rely *only* on Security Through Obscurity.

Simple obfuscation of the password (not actual encryption, but just storing it in a way that isn't obvious) can help, since it isn't then easy to see where in a memory dump the password would be. Splitting it up and scattering it around the place, too, can be useful.

Basically there is no simple answer, other than *make it as hard for an attacker to find sensitive things as possible* and *don't tell anyone what you have done to hide it* ;)

# Answer
> 3 votes
Unfortunately, I don't have a precise answer to your question currently, but I would like to warn you about the Security Through Obscurity approach proposed by Majenko. This approach may be reasonable for something very homemade, but it is strongly discouraged by researchers and experts.

For instance, if you have a look at the Guide to General Server Security you will read between the "Server Security Principle":

> Open Design—System: security should not depend on the secrecy of the implementation or its components.

So, try always to use a standard approach if you can.

---
Tags: wifi
---


# Question
Title: Teensy 4.1 serial communication with 7N2 (7 databits no parity 2 stopbits)
I have ported a project from arduino Due to a teensy 4.1

In the project I read data from a sensor which speaks serial at 7 databits, no parity and 2 stopbits (no configurable).

Now it seems that teensy does not support this dataformat. Could I read my sensor in a way using teensy 4.1? I could maybe use softwareserial but the format does not seem to be configurable.

# Answer
> 0 votes
There is no difference between 7N2 and 8N1. You just have the most significant bit of your data value being the first of the two stop bits.

To transmit just set the most significant bit to 1.

To receive just ignore the most significant bit.

For example:

```
Serial.write(val | 0x80);

```

And:

```
uint8_t val = Serial.read() & 0x7F;

```

---
Tags: serial, teensy
---


# Question
Title: Send button only works when pressed immediately after
I am new to Arduino and I am trying to create a Morse code based "chat".

I can submit a message in Morse code using the send button (the one on the right,) and when I press the button on the left and the whole decoded message should appear on the screen. However, this is not happening unless I press the send button immediately after introducing the Morse code. Can anyone help me out? I tried changing the delay period, but nothing seems to make it send how it should.

As I said, I am a beginner, so please go easy on me.

This is my code:

```
/* String tone = "-... ..- -. .- ";

  Morse code - Receiver

  modified on 14 Apr 2019
  by Saeed Hosseini @ Electropeak
  https://electropeak.com/learn

*/
#include <LiquidCrystal.h>
// Create an LCD object. Parameters: (RS, E, D4, D5, D6, D7):
LiquidCrystal lcd = LiquidCrystal(2, 3, 4, 5, 6, 7);
String code = "";
int len = 0;
char ch;
int ok;
char new_char;
int i1=0;
int i2=1;
const int but_send=8;
const int but = 12;
const int led = 13;
String a="";
unsigned long pres_len = 0, rel_time, pres_time = 0, old_time_len = 0, old_pres = 0, space = 0;
int state = 0;
int unit_delay = 250;
int min_delay = 10;
int buttonState = 0;

char MakeString()
{
  if (pres_len < (unit_delay*3) && pres_len > 50)
  {
    return '.';                        //if button press less than 0.6sec, it is a dot
  }
  else if (pres_len > (unit_delay*3))
  {
    return '-';                        //if button press more than 0.6sec, it is a dash
  }
}

void Morse_decod()
{
  static String morse[] = {".-", "-...", "-.-.", "-..", ".", "..-.", "--.", "....",
                             "..", ".---", "-.-", ".-..", "--", "-.", "---", ".--.", "--.-",
                             ".-.", "...", "-", "..-", "...-", ".--", "-..-", "-.--", "--..", "!"
                            };
  int i = 0;
  while (morse[i] != "!")
  {
    if (morse[i] == code)
    {
      Serial.print(char('A' + i));
      a=a+char('A' + i);
      //lcd.print(char('A' + i));
      Serial.print(" ");
      if(i2>=2)
      {
        i1++;
        i2=0;
      }
      else
      {i2++;
      }
      break;
    }
    i++;
  }
  if (morse[i] == "!")
  {
    Serial.println("");
    Serial.println("This code is not exist!");
  }

  code = "";
}
void sendText()
{
  Serial.println(digitalRead(but_send));
  // check if the pushbutton is pressed.
  // if it is, the buttonState is HIGH:
  //if (digitalRead(but_send) == HIGH) {
    // turn LED on:
     //gitalWrite(led, HIGH);
  if(ok==1){
    Serial.println(a);}
  ok=0;

    //}
  //else {
    // turn LED off:
    //Serial.println("NIMIC");
  //}
 delay(200);
}
void setup() {
  Serial.begin(9600);
  pinMode(but, INPUT_PULLUP);
  pinMode(but_send, INPUT_PULLUP);
  pinMode(led, OUTPUT);
  lcd.setCursor(i1, 12);
  lcd.begin(16, 2);

}
void loop() {
label:
  while (digitalRead(but) == HIGH) {}
  old_pres = rel_time;
  pres_time = millis();
  digitalWrite(led, HIGH);
  while (digitalRead(but) == LOW) {}
  rel_time = millis();
  digitalWrite(led, LOW);
  pres_len = rel_time - pres_time;
  space = pres_time - old_pres;
  if (pres_len > min_delay)
  {
    code += MakeString();
  }
  while ((millis() - rel_time) < (unit_delay * 3))
  {

    if (digitalRead(but) == LOW)
    {
      goto label;

    }

  }

  Morse_decod();
    delay(1000);
  if (digitalRead(but_send) == LOW)
  {
    ok=1;
    //Serial.println("A intrat aici");
    sendText();
    //delay(100);

  }

 //Serial.println(digitalRead(but_send));

}

```

This is what should happen all the time, not only after pressing the send button very fast:

If needed, I can send a link from my tinkercad simulation.

# Answer
> 3 votes
tavis’ answer nailed down your problem: your program is completely unresponsive when it is blocked in the first `while` loop of the `loop()` function. Here I will try to give you some hints on how to avoid this situation, but first some general comments:

> ```
> if (pres_len < (unit_delay*3) && pres_len > 50)
>
> ```

The threshold should be `unit_delay*2`, maybe with a longer `unit_delay`. In Morse, a dot is one unit, and a dash is three units. If you have to set a threshold, it should be somewhere in the middle. Otherwise, a perfectly valid dash of 2.99 units would be mistaken for a dot.

Also, a function returning anything but `void` should *always* return a value. What is this function supposed to return if `press_len` is smaller or equal than 50? And if it is exactly equal to `unit_delay*3`? The best way to make sure you did not forget any case is to have an `else` at the end that returns a default value in case no condition matches:

```
else
    return '?';  // we could not understand

```

In this particular case, it seems to me like you already did the debounce prior to calling the function, so it could be simplified to

```
char getSymbol()
{
    if (pres_len < 2 * unit_delay)
        return '.';
    else
        return '-';
}

```

Note that giving functions meaningful names is an important step in making the code easy to understand and reason about.

> ```
> if(i2>=2)
> {
>   i1++;
>   i2=0;
> }
> else
> {i2++;
> }
>
> ```

All this serves no useful purpose, as you do not use `i1` or `i2` after `setup()`. Removing useless stuff is also important for the clarity of the code.

> ```
> Serial.println("This code is not exist!");
>
> ```

It should say “I cannot understand this code!”, but it may well exist.

Now, to the core of the issue. If you want the program to be responsive, you should embrace *non-blocking programming*. This means getting rid of `delay()` (see Blink Without Delay) and getting rid of blocking loops, like the two `while` loops at the top of `loop()`. A very useful approach is to program your system as a finite state machine. Please, take the time to read and digest these two resources.

Next, as an example, I can point you to a Morse decoder of mine that is based on the finite state machine concept. You do not have have to look at my code, which may be too low level for your taste, but look at the documentation of the program internals. It explains how the state machines are built and interact with one another. Below is a state diagram taken from that documentation. It shows the state machine that takes the debounced “rise” and “fall” events as inputs, and generates “dot”, “dash”, “end-of-char” and “end-of-word” symbols as outputs:

# Answer
> 2 votes
It looks like the line : while (digitalRead(but) == HIGH) {} will capture the processor in a loop until "but" is pressed. So if you press the send button immediately after using "but" it might see that you pressed "send", but if you let the program loop get back to while (digitalRead(but) == HIGH) {}, then nothing can happen until "but" is pressed again.

# Answer
> 1 votes
Both tavis and Edgar Bonet have hit the nail on the head, and Edgar has provided you with an excellent tutorial.

You are unlikely to get this to work properly in the Tinkercad browser simulator because it runs at different speeds depending on the complexity of the code it is running. And the complexity varies when you press buttons, which throws the timing out as the Morse button is pressed.

However, I managed to get it roughly working in Tinkercad as follows.

```
#include <LiquidCrystal.h>

LiquidCrystal lcd(12, 11, 5, 4, 3, 2);

const byte MORSE_BUTTON_PIN = 6;
const byte SEND_BUTTON_PIN = 7;
const byte MORSE_LED_PIN = 8;

const unsigned long DEBOUNCE_DELAY_ms = 50;
const unsigned long MORSE_UNIT_1 = 500;  // milliseconds.
const unsigned long MORSE_UNIT_2 = 2 * MORSE_UNIT_1;  // milliseconds.
const unsigned long MORSE_UNIT_5 = 5 * MORSE_UNIT_1;  // milliseconds.

const String MORSE_CODES[] =
{
  ".-", "-...", "-.-.", "-..", ".",
  "..-.", "--.", "....", "..", ".---",
  "-.-", ".-..", "--", "-.", "---",
  ".--.", "--.-", ".-.", "...", "-",
  "..-", "...-", ".--", "-..-", "-.--",
  "--.."
};

String symbol;
String message;

Debouncer morse_button(MORSE_BUTTON_PIN, DEBOUNCE_DELAY_ms);
Debouncer send_button(SEND_BUTTON_PIN, DEBOUNCE_DELAY_ms);

void setup()
{
  Serial.begin(115200);
  pinMode(MORSE_BUTTON_PIN, INPUT);
  pinMode(SEND_BUTTON_PIN, INPUT);
  pinMode(MORSE_LED_PIN, OUTPUT);
  // Set up the LCD's number of columns and rows:
  lcd.begin(16, 2);
  // Print a message to the LCD.
  lcd.print("Hello, world!");
}

void loop()
{
  static unsigned long press_begin_time = 0;
  static unsigned long release_begin_time = 0;
  static bool measure_the_gap = false;

  morse_button.Update();
  send_button.Update();

  if (morse_button.Fall())
  {
    // Remember when the morse button was pressed and
    // switch on the LED.
    int timestamp = millis();
    digitalWrite(MORSE_LED_PIN, HIGH);
    press_begin_time = timestamp;
  }

  if (morse_button.Rise())
  {
    // Remember when the morse button was released and
    // switch off the LED.
    int timestamp = millis();
    digitalWrite(MORSE_LED_PIN, LOW);
    release_begin_time = timestamp;
    int pressed_time = timestamp - press_begin_time;
    if (pressed_time > MORSE_UNIT_2)
    {
      // Dash.
      //Serial.print("-");
      symbol += "-";
    }
    else
    {
      // Dot.
      //Serial.print(".");
      symbol += ".";
    }
    measure_the_gap = symbol.length() > 0;
  }

  if (measure_the_gap)
  {
    unsigned long timestamp = millis();
    //Serial.println("Measuring the gap.");
    if (((timestamp - release_begin_time) > MORSE_UNIT_2))
    {
      // A long gap between presses signifies the end of a symbol.
      //Serial.println("Long gap");
      //Serial.println(symbol);
      measure_the_gap = false;
      message += DecodeSymbol(symbol);
      symbol = "";
    }
  }

  if (send_button.Fall())
  {
    // Print the Morse string.
    //Serial.println(message);
    lcd.clear();
    lcd.setCursor(0, 1);
    lcd.print(message);
    message = "";
  }

  // Delay for Tinkercad simulator.
  // Not needed for real hardware.
  delay(10);
}

char DecodeSymbol(String& symbol)
{
  //Serial.print(symbol);
  //Serial.print(": ");
  char ch = '?';
  for (int i = 0; i < 26; i++)
  {
    if (symbol == MORSE_CODES[i])
    {
      ch = 'A' + i;
      break;
    }
  }
  //Serial.println(ch);
  return ch;
}

```

For debouncing the buttons, I used this debouncer that I've put on GitHub. For Tinkercad, you will need to copy and paste that debouncer code (the debouncer.h file followed by the debouncer.cpp file) into the top of the Tnkercad code file because Tinkercad doesn't allow you to include your own code files.

---
Tags: arduino-uno, interrupt, button
---


# Question
Title: ST7735s 1.8" SPI 128x160 TFT Module - White Screen
I am having an issue in my 1.8" TFT LCD module with SPI interface in Arduino Nano. I keep seeing the white screen on my tft.

I have made the following connections using Jumper cables:

* 1. RST --- connected to D8 (on Nano)
* 2. CE/CS --- Connected to D10
* 3. DC ---- Connected to D9
* 4. DIN (MOSI) -- connected to D11
* 5. CLK --- connected to D13
* 6. VCC --- connected to 5V
* 7. BL ---- Connected to 3.3 V
* 8. GND -- connected to GND

Sorry i am new to this world, so dont know how i can provide you the wiring connections i have made and so jotted it down in this post.

I am using the Adafruit ST7735 GraphicsTest with the code modified according to the above pin:

```
/**************************************************************************
  This is a library for several Adafruit displays based on ST77* drivers.

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

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

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

  Written by Limor Fried/Ladyada for Adafruit Industries.
  MIT license, all text above must be included in any redistribution
 **************************************************************************/

#include <Adafruit_GFX.h>    // Core graphics library
#include <Adafruit_ST7735.h> // Hardware-specific library for ST7735
#include <Adafruit_ST7789.h> // Hardware-specific library for ST7789
#include <SPI.h>

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

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

#else
  // For the breakout board, you can use any 2 or 3 pins.
  // These pins will also work for the 1.8" TFT shield.
  #define TFT_CS        10
  #define TFT_RST        8 // Or set to -1 and connect to Arduino RESET pin
  #define TFT_DC         9
#endif

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

// For 1.44" and 1.8" TFT with ST7735 use:
// Adafruit_ST7735 tft = Adafruit_ST7735(TFT_CS, TFT_DC, TFT_RST);

// For 1.14", 1.3", 1.54", and 2.0" TFT with ST7789:
//Adafruit_ST7789 tft = Adafruit_ST7789(TFT_CS, TFT_DC, TFT_RST);

// OPTION 2 lets you interface the display using ANY TWO or THREE PINS,
// tradeoff being that performance is not as fast as hardware SPI above.
#define TFT_MOSI 11  // Data out
#define TFT_SCLK 13  // Clock out

// For ST7735-based displays, we will use this call
Adafruit_ST7735 tft = Adafruit_ST7735(TFT_CS, TFT_DC, TFT_MOSI, TFT_SCLK, TFT_RST);

// OR for the ST7789-based displays, we will use this call
//Adafruit_ST7789 tft = Adafruit_ST7789(TFT_CS, TFT_DC, TFT_MOSI, TFT_SCLK, TFT_RST);

float p = 3.1415926;

void setup(void) {
  Serial.begin(9600);
  Serial.print(F("Hello! ST77xx TFT Test"));

  // Use this initializer if using a 1.8" TFT screen:
  tft.initR(INITR_BLACKTAB);      // Init ST7735S chip, black tab

  // OR use this initializer if using a 1.8" TFT screen with offset such as WaveShare:
  // tft.initR(INITR_GREENTAB);      // Init ST7735S chip, green tab

  // OR use this initializer (uncomment) if using a 1.44" TFT:
  //tft.initR(INITR_144GREENTAB); // Init ST7735R chip, green tab

  // OR use this initializer (uncomment) if using a 0.96" 160x80 TFT:
  //tft.initR(INITR_MINI160x80);  // Init ST7735S mini display

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

  // OR use this initializer (uncomment) if using a 2.0" 320x240 TFT:
  //tft.init(240, 320);           // Init ST7789 320x240

  // OR use this initializer (uncomment) if using a 1.14" 240x135 TFT:
  //tft.init(135, 240);           // Init ST7789 240x135

  // SPI speed defaults to SPI_DEFAULT_FREQ defined in the library, you can override it here
  // Note that speed allowable depends on chip and quality of wiring, if you go too fast, you
  // may end up with a black screen some times, or all the time.
  //tft.setSPISpeed(40000000);

  Serial.println(F("Initialized"));

  uint16_t time = millis();
  tft.fillScreen(ST77XX_BLACK);
  time = millis() - time;

  Serial.println(time, DEC);
  delay(500);

  // large block of text
  tft.fillScreen(ST77XX_BLACK);
  testdrawtext("Lorem ipsum dolor sit amet, consectetur adipiscing elit. Curabitur adipiscing ante sed nibh tincidunt feugiat. Maecenas enim massa, fringilla sed malesuada et, malesuada sit amet turpis. Sed porttitor neque ut ante pretium vitae malesuada nunc bibendum. Nullam aliquet ultrices massa eu hendrerit. Ut sed nisi lorem. In vestibulum purus a tortor imperdiet posuere. ", ST77XX_WHITE);
  delay(1000);

  // tft print function!
  tftPrintTest();
  delay(4000);

  // a single pixel
  tft.drawPixel(tft.width()/2, tft.height()/2, ST77XX_GREEN);
  delay(500);

  // line draw test
  testlines(ST77XX_YELLOW);
  delay(500);

  // optimized lines
  testfastlines(ST77XX_RED, ST77XX_BLUE);
  delay(500);

  testdrawrects(ST77XX_GREEN);
  delay(500);

  testfillrects(ST77XX_YELLOW, ST77XX_MAGENTA);
  delay(500);

  tft.fillScreen(ST77XX_BLACK);
  testfillcircles(10, ST77XX_BLUE);
  testdrawcircles(10, ST77XX_WHITE);
  delay(500);

  testroundrects();
  delay(500);

  testtriangles();
  delay(500);

  mediabuttons();
  delay(500);

  Serial.println("done");
  delay(1000);
}

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

void testlines(uint16_t color) {
  tft.fillScreen(ST77XX_BLACK);
  for (int16_t x=0; x < tft.width(); x+=6) {
    tft.drawLine(0, 0, x, tft.height()-1, color);
    delay(0);
  }
  for (int16_t y=0; y < tft.height(); y+=6) {
    tft.drawLine(0, 0, tft.width()-1, y, color);
    delay(0);
  }

  tft.fillScreen(ST77XX_BLACK);
  for (int16_t x=0; x < tft.width(); x+=6) {
    tft.drawLine(tft.width()-1, 0, x, tft.height()-1, color);
    delay(0);
  }
  for (int16_t y=0; y < tft.height(); y+=6) {
    tft.drawLine(tft.width()-1, 0, 0, y, color);
    delay(0);
  }

  tft.fillScreen(ST77XX_BLACK);
  for (int16_t x=0; x < tft.width(); x+=6) {
    tft.drawLine(0, tft.height()-1, x, 0, color);
    delay(0);
  }
  for (int16_t y=0; y < tft.height(); y+=6) {
    tft.drawLine(0, tft.height()-1, tft.width()-1, y, color);
    delay(0);
  }

  tft.fillScreen(ST77XX_BLACK);
  for (int16_t x=0; x < tft.width(); x+=6) {
    tft.drawLine(tft.width()-1, tft.height()-1, x, 0, color);
    delay(0);
  }
  for (int16_t y=0; y < tft.height(); y+=6) {
    tft.drawLine(tft.width()-1, tft.height()-1, 0, y, color);
    delay(0);
  }
}

void testdrawtext(char *text, uint16_t color) {
  tft.setCursor(0, 0);
  tft.setTextColor(color);
  tft.setTextWrap(true);
  tft.print(text);
}

void testfastlines(uint16_t color1, uint16_t color2) {
  tft.fillScreen(ST77XX_BLACK);
  for (int16_t y=0; y < tft.height(); y+=5) {
    tft.drawFastHLine(0, y, tft.width(), color1);
  }
  for (int16_t x=0; x < tft.width(); x+=5) {
    tft.drawFastVLine(x, 0, tft.height(), color2);
  }
}

void testdrawrects(uint16_t color) {
  tft.fillScreen(ST77XX_BLACK);
  for (int16_t x=0; x < tft.width(); x+=6) {
    tft.drawRect(tft.width()/2 -x/2, tft.height()/2 -x/2 , x, x, color);
  }
}

void testfillrects(uint16_t color1, uint16_t color2) {
  tft.fillScreen(ST77XX_BLACK);
  for (int16_t x=tft.width()-1; x > 6; x-=6) {
    tft.fillRect(tft.width()/2 -x/2, tft.height()/2 -x/2 , x, x, color1);
    tft.drawRect(tft.width()/2 -x/2, tft.height()/2 -x/2 , x, x, color2);
  }
}

void testfillcircles(uint8_t radius, uint16_t color) {
  for (int16_t x=radius; x < tft.width(); x+=radius*2) {
    for (int16_t y=radius; y < tft.height(); y+=radius*2) {
      tft.fillCircle(x, y, radius, color);
    }
  }
}

void testdrawcircles(uint8_t radius, uint16_t color) {
  for (int16_t x=0; x < tft.width()+radius; x+=radius*2) {
    for (int16_t y=0; y < tft.height()+radius; y+=radius*2) {
      tft.drawCircle(x, y, radius, color);
    }
  }
}

void testtriangles() {
  tft.fillScreen(ST77XX_BLACK);
  uint16_t color = 0xF800;
  int t;
  int w = tft.width()/2;
  int x = tft.height()-1;
  int y = 0;
  int z = tft.width();
  for(t = 0 ; t <= 15; t++) {
    tft.drawTriangle(w, y, y, x, z, x, color);
    x-=4;
    y+=4;
    z-=4;
    color+=100;
  }
}

void testroundrects() {
  tft.fillScreen(ST77XX_BLACK);
  uint16_t color = 100;
  int i;
  int t;
  for(t = 0 ; t <= 4; t+=1) {
    int x = 0;
    int y = 0;
    int w = tft.width()-2;
    int h = tft.height()-2;
    for(i = 0 ; i <= 16; i+=1) {
      tft.drawRoundRect(x, y, w, h, 5, color);
      x+=2;
      y+=3;
      w-=4;
      h-=6;
      color+=1100;
    }
    color+=100;
  }
}

void tftPrintTest() {
  tft.setTextWrap(false);
  tft.fillScreen(ST77XX_BLACK);
  tft.setCursor(0, 30);
  tft.setTextColor(ST77XX_RED);
  tft.setTextSize(1);
  tft.println("Hello World!");
  tft.setTextColor(ST77XX_YELLOW);
  tft.setTextSize(2);
  tft.println("Hello World!");
  tft.setTextColor(ST77XX_GREEN);
  tft.setTextSize(3);
  tft.println("Hello World!");
  tft.setTextColor(ST77XX_BLUE);
  tft.setTextSize(4);
  tft.print(1234.567);
  delay(1500);
  tft.setCursor(0, 0);
  tft.fillScreen(ST77XX_BLACK);
  tft.setTextColor(ST77XX_WHITE);
  tft.setTextSize(0);
  tft.println("Hello World!");
  tft.setTextSize(1);
  tft.setTextColor(ST77XX_GREEN);
  tft.print(p, 6);
  tft.println(" Want pi?");
  tft.println(" ");
  tft.print(8675309, HEX); // print 8,675,309 out in HEX!
  tft.println(" Print HEX!");
  tft.println(" ");
  tft.setTextColor(ST77XX_WHITE);
  tft.println("Sketch has been");
  tft.println("running for: ");
  tft.setTextColor(ST77XX_MAGENTA);
  tft.print(millis() / 1000);
  tft.setTextColor(ST77XX_WHITE);
  tft.print(" seconds.");
}

void mediabuttons() {
  // play
  tft.fillScreen(ST77XX_BLACK);
  tft.fillRoundRect(25, 10, 78, 60, 8, ST77XX_WHITE);
  tft.fillTriangle(42, 20, 42, 60, 90, 40, ST77XX_RED);
  delay(500);
  // pause
  tft.fillRoundRect(25, 90, 78, 60, 8, ST77XX_WHITE);
  tft.fillRoundRect(39, 98, 20, 45, 5, ST77XX_GREEN);
  tft.fillRoundRect(69, 98, 20, 45, 5, ST77XX_GREEN);
  delay(500);
  // play color
  tft.fillTriangle(42, 20, 42, 60, 90, 40, ST77XX_BLUE);
  delay(50);
  // pause color
  tft.fillRoundRect(39, 98, 20, 45, 5, ST77XX_RED);
  tft.fillRoundRect(69, 98, 20, 45, 5, ST77XX_RED);
  // play color
  tft.fillTriangle(42, 20, 42, 60, 90, 40, ST77XX_GREEN);
}

```

The Output of this code on serial output:

```
01:16:16.840 -> Hello! ST77xx TFT TestInitialized
01:16:19.829 -> 1876
01:17:44.911 -> done

```

I have tried many things from past two days but no luck on this issue. I have seen the following posts and implemented but effort gone in just accumulating knowledge but unable to resolve the issues:

What am I missing? ST7735 TFT white screen Why am I only seeing white screen in TFT 1.44 ST7735?

Kindly please let me know in case anyone resolves this issue.

# Answer
> 1 votes
I have a 1.44' SPI 128x128 V2.0 \[Blueish (teal) PCB, Green Tab Screen\].

I was having the same problem. I had connected the VCC pin to 3.3V.

Solution: connect VCC to the 5V pin

The white screen is gone. I hope it helps.

---
Tags: lcd, spi, tft
---


# Question
Title: What kind of distance sensor are optimal to measure distances to surfaces at an angle to the sensor?
I want to try measuring the orientation of an object by measuring the distance between a "flat" surface to the surface of the rotated object. The problem I assume is that if the surface being measured is at an angle to the distance sensors, the beamed lights from laser or infrared proximity sensors, for example, would be reflected at an angle and not return to the sensors at all.  Would this actually happen, or am I misunderstanding some properties of these sensors? Which sensors would work in this kind of application, and which sensors would not work for sure (I read from another post that ultrasonic sensors would definitely not work in this case)?

(Added a crude sketch of the problem I think is going to happen)

# Answer
> 2 votes
Using ultrasonic sensors would be a very sensible solution in your use case.

I am currently working on a similar project with a company in Denmark, where the objective is to detect cars on parking spaces. For this task, I used two of these ultrasonic sensors from DFRobot for the prototype:

https://www.dfrobot.com/product-1935.html

They were very easy and simple to setup on an Arduino UNO and worked perfectly fine even when two were sensing at once. Though I have to mention, that they need a serial connection each, but this can be worked around using a multiplexer or a developer board with more serial connections.

I also found that the ultrasonic sensors work better than time of flight sensors in outdoor conditions. They are very robust and wont be as affected by dirt for instance. A little speck on the lens of a ToF sensor and it will be rendered useless.

Ultrasonic sensors are also widely used in the car industry for parking aid solutions where they have to detect lots of different surfaces and be very precise in doing so.

Ultrasonic sensors are great. And yes, they can interfere with each other, but as long as you dont put them on top of one another, it should not be an issue.

You should be able to detect the distance to a trailer in two different places using ultrasonic sensors as long as the trailer is within the sensors range.

---
Tags: sensors
---


# Question
Title: How to control Keyboard inputs using arduino(serial monitor) and python keyboard libraries?
I am able to control my monitor and most other applications by giving serial input to python through arduino. Arduino code:

```
void setup()
 {

  pinMode(2, INPUT);
  pinMode(3, INPUT);
  pinMode(4, INPUT);
  pinMode(5, INPUT);
  pinMode(6, INPUT);
  pinMode(7, INPUT);
  Serial.begin(9600);

}

void loop()
{
  if(digitalRead(2) == HIGH)
  {
    delay(5);
  }
  else
  {
    Serial.println("up");
  }
  if(digitalRead(3) == HIGH)
  {
    delay(5);
  }
  else
  {
    Serial.println("down");
  }
  if(digitalRead(4) == HIGH)
  {
    delay(5);
  }
  else
  {
    Serial.println("left");
  }
  if(digitalRead(5) == HIGH)
  {
    delay(5);
  }
  else
  {
    Serial.println("right");
  }
  if(digitalRead(6)== HIGH)
  {
    delay(5);
  }
  else
  {
    Serial.println("space");//orange
  }
  if(digitalRead(7)==HIGH)
  {
     delay(5);
  }
  else
  {
    Serial.println("nitro");//brown
  }
 }

```

Python code:

```
import serial
from pymouse import PyMouse
from pykeyboard import PyKeyboard

k = PyKeyboard()

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

#sp.write("AT\r\n".encode('ascii'))

while True:
    p=ser.readline()
    print p
    if ('up' in p):
        k = PyKeyboard()

        k.tap_key(k.up_key)

    if ('down' in p):
        k = PyKeyboard()

        k.tap_key(k.down_key)

    if ('right' in p):
        k = PyKeyboard()

        k.tap_key(k.right_key)

    if ('left' in p):
        k = PyKeyboard()

        k.tap_key(k.left_key)

    if ('space' in p):
        k = PyKeyboard()

        k.tap_key(k.space_key)

    if ('nitro' in p):
        k = PyKeyboard()

        k.tap_key(k.enter_key)

```

My problem is that..I am not able to play games such as NFS and other similar games using these controls.. What should i do??

# Answer
Your examples of sending input to the Arduino IDE monitor and to Python involve the Arduino sending data via "Serial over USB" convention. However this is not seen by the operating system (Windows, MacOS) as legitimate keyboard/mouse/joystick input.

There are separate USB conventions (device types) for keyboard/mouse/joystick. Only Arduinos where the USB interface is programmable are able to present those conventions, and some more easily than others, and require understanding some USB client libraries. The link provided by Chris Stratton has some useful background.

A particularly easy way to get into this is with the PJRC Teensy, https://www.pjrc.com/teensy/, which comes with libraries and examples that let you do this out-of-the-box. See the "Teensyduino" section of their website for USB Keyboard, Mouse, Joystick and so on. These pages are useful background even if not using Teensy. It has attracted a small following of users interested in this area. Plus the various Teensies are conveniently small boards that fits nicely in some user-interface device you might want to build.
> 2 votes

# Answer
I'm later, but, I think you should redesign your python and arduino code, to make messages like "start up", "end up", and if message is "start \*", hold that key, if "end \*", release that key. This should work as intended. I will pin python and arduino code later here. (Also sorry for my english, i'm russian)
> 1 votes

---
Tags: arduino-uno
---


# Question
Title: How to add colour change to the strobe coding?
I have this strobe effect working. However, I would like to change the colour of the LEDs after each 'strobe sequence'. How can it be achieved? The code I am using is this one:

```
    // Basic code NeoPixel
    // wwww.arduinoplatform.com

    #include <Adafruit_NeoPixel.h>
    #ifdef __AVR__
     #include <avr/power.h> // Required for 16 MHz Adafruit Trinket
    #endif

    // Which pin on the Arduino is connected to the NeoPixels?
    // On a Trinket or Gemma we suggest changing this to 1:
    #define LED_PIN    6

    // How many NeoPixels ar
    Adafruit_NeoPixel strip = Adafruit_NeoPixel(60, 6, NEO_GRB + NEO_KHZ800);

    void setup() {
      strip.begin();
      strip.show(); // Initialize all pixels to 'off'
    }

    // *** REPLACE FROM HERE ***

    void loop() {
      // Slower:
      // Strobe(0xff, 0x77, 0x00, 10, 100, 1000);
      // Fast:
      Strobe(0xFF, 0x00, 0xF8, 10, 50, 1000);
    }

    void Strobe(byte red, byte green, byte blue, int StrobeCount, int FlashDelay, int EndPause){
      for(int j = 0; j < StrobeCount; j++) {
        setAll(red,green,blue);
        showStrip();
        delay(FlashDelay);
        setAll(0,0,0);
        showStrip();
        delay(FlashDelay);
      }

     delay(EndPause);
    }

    // *** REPLACE TO HERE ***

    void showStrip() {
     #ifdef ADAFRUIT_NEOPIXEL_H
       // NeoPixel
       strip.show();
     #endif

    }

    void setPixel(int Pixel, byte red, byte green, byte blue) {
     #ifdef ADAFRUIT_NEOPIXEL_H
       // NeoPixel
       strip.setPixelColor(Pixel, strip.Color(red, green, blue));
     #endif
    }

    void setAll(byte red, byte green, byte blue) {
      for(int i = 0; i < 64; i++ ) {
        setPixel(i, red, green, blue);
      }
      showStrip();
    }

```

# Answer
> 1 votes
I guess you want to cycle through a list of defined colors with your strobe effect. For that you can save the colors in a 2-dimensional array and then cycle through the array with a for loop. The 2-dimensional array is then a group of colors, each defined by the 3 numbers for a RGB value. Somewhat like this:

```
#define NUM_COLORS   5
byte colors[NUM_COLORS][3] = {
    {0xFF, 0, 0},
    {0, 0xFF, 0},
    {0, 0, 0xFF},
    {0xFF, 0xFF, 0},
    {0, 0xFF, 0xFF}
};

void loop(){
    for(int i=0;i<NUM_COLORS;i++){
        Strobe(colors[i][0], colors[i][1], colors[i][2], 10, 50, 1000);
    }
}

```

Note, that this is not a complete code, but only the interesting parts. You can incorporate this into your code. You can change the number of colors and the colors itself to your liking (I only took some example values, that are easy to recognize).

---
Tags: arduino-nano
---


# Question
Title: AccelStepper Library Help - Simultaneous Motor Driving
I’m working on a 4 wheeled robot driven with stepper motors. I have a Raspberry Pi that sends a random (based on input image) pulse count to the Arduino board serially and then steps that amount. I’m using an Arduino CNC board to drive all 4 stepper motors, just FYI. My problem is that currently my steppers will not simultaneously move. I’ve read over the documentation for the AccelStepper library pretty well and tried some of the example code with no luck. I have a lot of function/ parsing code prior to the actual stepper code. It’s almost at the end, the function called ‘yMovement’. Currently, the int value is received then yStepper moves, then yStepper1 moves after.

My updated code now makes them move simultaneously but the done command does not behave as before.

```
#include <AccelStepper.h>

const int stepperCount = 4;
AccelStepper FLStepper(AccelStepper::FULL2WIRE, 2, 5);
AccelStepper FRStepper(AccelStepper::FULL2WIRE, 3, 6);
AccelStepper BRStepper(AccelStepper::FULL2WIRE, 4, 7);
AccelStepper BLStepper(AccelStepper::FULL2WIRE, 12, 13);

bool movementComplete = false;

// defines pins numbers

//Front left wheel
const int stepX = 2;
const int dirX  = 5;

//Front right wheel
const int stepY = 3;
const int dirY  = 6;

//Back left wheel
const int stepZ = 4;
const int dirZ  = 7;

//Back right wheel
const int stepA = 12;
const int dirA  = 13;
const int enPin = 8;

char split = ':';         //this is the character that would be used for seperating the different parts of your commands
                          //the syntax for commands would be:   command:value1:value2

int listSize = 5;                                     //the amount of commands in the list
String commands[] = {"hello", "add", "sub", "YMOV", "XMOV"};     //the list of every command name

void setup()
{
  Serial.begin(115200);     //sets the data transfer rate for the serial interface
                          //9600 is good for basic testing, but should be as high
                          //as possible for both devices.
  FRStepper.setMaxSpeed(500);
  FRStepper.setAcceleration(400);
  BRStepper.setMaxSpeed(500);
  BRStepper.setAcceleration(400);

  FLStepper.setMaxSpeed(500);
  FLStepper.setAcceleration(400);
  BLStepper.setMaxSpeed(500);
  BLStepper.setAcceleration(400);

  pinMode(stepX, OUTPUT);
  pinMode(dirX, OUTPUT);

  pinMode(stepY, OUTPUT);
  pinMode(dirY, OUTPUT);

  pinMode(stepZ, OUTPUT);
  pinMode(dirZ, OUTPUT);

  pinMode(enPin, OUTPUT);

  digitalWrite(enPin, LOW);
  digitalWrite(dirX, HIGH);
  digitalWrite(dirY, HIGH);
  digitalWrite(dirZ, HIGH);
  digitalWrite(dirA, HIGH);

}

void loop()
{
  CommCheck(); //checks serial buffer for data commands
  runMotors();
}

void runMotors()
{

  if ((FLStepper.distanceToGo() != 0) || (FRStepper.distanceToGo() != 0) || (BLStepper.distanceToGo() != 0) || (BRStepper.distanceToGo() != 0))
  {

    FLStepper.run();
    //BLStepper.run();
    FRStepper.run();
    //BRStepper.run();
    movementComplete = true;
  }
  if (movementComplete == true)
  {
    CommConfirm();
    movementComplete = false;
  }
  //if ((FLStepper.distanceToGo() == 0) && (FRStepper.distanceToGo() == 0) && (BLStepper.distanceToGo() == 0) && (BRStepper.distanceToGo() == 0))
  //if ((FLStepper.distanceToGo() == 0) || (FRStepper.distanceToGo() == 0) || (BLStepper.distanceToGo() == 0) || (BRStepper.distanceToGo() == 0))
  //{
    //movementComplete = true;
  //}
}
void CommCheck()
{
  if(Serial.available())                    //checks to see if there is serial data has been received
  {
    //int len = Serial.available();           //stores the character lengh of the command that was sent
                                             //this is used for command parsing later on

    String command = Serial.readString();   //stores the command as a text string
    int len = command.length();
    //Serial.println(command);
    Serial.flush();
    //command.remove(len-2,1);                //removes characters added by the pi's serial data protocol
    //command.remove(0,2);
    //len -= 3;                               //updates the string length value for parsing routine

    int points[2] = {0, 0};                 //offset points for where we need to split the command into its individual parts

    for(int x = 0; x < len; x++)            //this loop will go through the entire command to find the split points based on
    {                                       //what the split variable declared at the top of the script is set to.
      //Serial.print("Char ");
      //Serial.print(x);
      //Serial.print("- ");
      //Serial.println(command[x]);
      if(command[x] == split)               //this goes through every character in the string and compares it to the split character
      {
        if(points[0] == 0)                  //if the first split point hasn't been found, set it to the current spot
        {
          points[0] = x;
        }
        else                                //if the first spot was already found, then set the second split point
        {                                   //this routine is currently only set up for a command syntax that is as follows
          points[1] = x;                    //command:datavalue1:datavalue2
        }
      }
    }
    CommParse(command, len, points[0], points[1]);      //now that we know the command, command length, and split points,
  }                                                     //we can then send that information out to a routine to split the data
}                                                       //into individual values.

void CommParse(String command, int len, int point1, int point2)
{
  //Serial.print("Command Length: ");
  //Serial.println(len);
  //Serial.print("Split 1: ");
  //Serial.println(point1);
  //Serial.print("Split 2: ");
  //Serial.println(point2);

  String com = command;                 //copy the full command into all 3 parts
  String val1 = command;                //this is needed for the string manipulation
  String val2 = command;                //that follow

  com.remove(point1, len - point1);     //each of these use the string remove to delete
  val1.remove(point2, len - point2);    //the parts of the command that aren't needed
  val1.remove(0, point1 + 1);           //basically splitting the command up into its
  val2.remove(0, point2 + 1);           //individual pieces
  val2.remove(val2.length()-1,1);

  CommLookup(com, val1, val2);    //these pieces are then sent to a lookup routine for processing
}

void CommLookup(String com, String val1, String val2)
{

  int offset = 255;                   //create a variable for our lookup table's offest value
                                      //we set this to 255 because there won't be 255 total commands
                                      //and a valid command can be offset 0, so it's just to avoid
                                      //any possible coding conflicts if the command sent doesn't
                                      //match anything.

  for(int x = 0; x < listSize; x++)   //this goes through the list of commands and compares
  {                                   //them against the command received
    if(commands[x] == com)
    {
      offset = x;                     //if the command matches one in the table, store that command's offset
    }
  }

  switch(offset)                //this code compares the offset value and triggers the appropriate command
  {
    case 0:                                 //essentially a hello world.                       |  Syntax: hello:null:null
      CommHello();                          //this activates the hello world subroutine        |  returns Hello!
      break;
    case 1:                                 //adds both values together and return the sum.    |  Syntax: add:value1:value2
      CommAdd(val1.toInt(), val2.toInt());  //this activates the addition subroutine           |  returns value1 + value2
      break;
    case 2:                                 //subtracts both values and return the difference  |  Syntax: subtract:value1:value2
      CommSub(val1.toInt(), val2.toInt());  //this activates the subtraction subroutine        |  returns value1 - value2
      break;
    case 3:
      yMovement(val1.toInt(), val2.toInt());
      break;
    case 4:
      xMovement(val1.toInt(), val2.toInt());
    default:                                        //this is the default case for the command lookup and will only
      Serial.println("Command not recognized");     //trigger if the command sent was not known by the arduino
      break;
  }
}

void CommHello()                               //each of these routines are what will be triggered when they are successfully processed
{
  Serial.println("Hello!");
  CommConfirm();
}

void CommAdd(int val1, int val2)
{
  Serial.println(val1 + val2);
  CommConfirm();
}

void CommSub(int val1, int val2)
{
  Serial.println(val1 - val2);
  CommConfirm();
}

void yMovement(int val1, int val2)
{
  if (val1 < 0) {
    int yMoveNew = (val1 * (-4));
    //Serial.println(val1 * (-1));
    //delay(500);

    FRStepper.moveTo(-yMoveNew);

    BRStepper.moveTo(-yMoveNew);

    FLStepper.moveTo(-yMoveNew);

    BLStepper.moveTo(-yMoveNew);

    //delayMicroseconds(500);
  }

  else {

    int yMoveNew = (val1 * 4);
    //Serial.println(val1);
    //delay(500);
    FRStepper.moveTo(yMoveNew);

    BRStepper.moveTo(yMoveNew);

    FLStepper.moveTo(yMoveNew);

    BLStepper.moveTo(yMoveNew);

    //delayMicroseconds(500);

  }
}

void xMovement(int val1, int val2)
{
  if (val1 < 0) {
    int xMoveNew = (val1 * (-4));
    //Serial.println(val1 * (-1));
    //delay(1000);
    FLStepper.moveTo(-xMoveNew);

    BLStepper.moveTo(-xMoveNew);

    FRStepper.moveTo(-xMoveNew);

    BRStepper.moveTo(-xMoveNew);

    //delayMicroseconds(500);
  }

  else {

    int xMoveNew = (val1 * 4);
    //Serial.println(val1);
    //delay(1000);
    FLStepper.moveTo(xMoveNew);

    BLStepper.moveTo(xMoveNew);

    FRStepper.moveTo(xMoveNew);

    BRStepper.moveTo(xMoveNew);

    //delayMicroseconds(500);

  }
}
void CommConfirm()
{
  Serial.println("Done");

}

```

# Answer
With the `AccelStepper.move()` function, you are setting the target position of the motor. Then you run the motor with `AccelStepper.runToPosition()`. But that is a blocking function. It will not exit, until the motor reached it's target position. So you just picked the wrong function from the `AccelStepper` library.

---

**Small adjacent about simultaneous action on microcontrollers:** Since most microcontrollers, like in the Arduino, only have one core, they can only do exactly one thing at a time. But you can still execute things one after another, but so fast, that a human would say, they where happening at the same time. For this we need to divide down the actions into small chunks, that are executed very fast. In your case we have the big actions of running multiple motors to their target positions. Each of these big actions take long in total, but we can divide them down. And with stepper motors that is really easy, because one step would be one small chunk of that action.

So we want to go through our code very fast, successively checking for each motor, if it is time to do a step with it. If yes, we only do that one step. Then we proceed further to the next motor.

---

The `AccelStepper` library helps you in doing this `checking if it is time to do a step`. This is what happens in the `AccelStepper.run()` function. You just need to call it regularily, fast enough to not miss the time for a step.

So the solution is to remove all the calls to `AccelStepper.runToPosition()` and instead call the `AccelStepper.run()` function for all your stepper motors directly in the `loop()` function.
> 1 votes

---
Tags: arduino-uno, stepper, stepper-motor
---


title: Arduino Uno R3 HID with HC-06 BT module

text:
# Question
Title: Arduino Uno R3 HID with HC-06 BT module
Im trying to make a macro pad using Arduino Uno r3 and 4x4 matrix (cherry blue clone) . I know using a pro micro is better than uno cause there isn't HID compatibility in uno but since i already have one , i want to work with this . I have already tested the macro pad after compiling and flashing a keyboard.hex file . But wondering if i buy a bt module like HC-06 (which is about 3.2$ here ) would that be able to send inputs even aftar flashing ? I have like basics coding knowledge so i have no clue what flashing actually would do to the module so . Anyone know would making that macro pad BT compatible be possible or not ?

# Answer
It is unclear to me, where you flashed what, so I will describe some basics.

The Uno cannot act as a keyboard/HID device, since the microcontroller on it (the Atmega328p) doesn't have native USB capability. For connecting to USB the Uno has a USB-to-Serial chip on it (actually another microcontroller, the Atmega32u4 I think). So with the Uno you only have a serial connection, unless you hack the Atmega32u4 and program it with your own firmware (firmware is a term for software, that runs very near to the hardware, in this case directly on the microcontroller, in contrast to normal software running on an operating system on a computer; so in the middle between hard- and software, thus **firm**ware).

Flashing is the same as programming a microcontroller. It has this name, because the program is saved in flash memory on the microcontroller (that is a specific type of memory technology; the same technology, that USB sticks use for storing your data). Flashing the HC-06 means programming it with a different firmware.

All bluetooth devices use the same base technology (thought to be clear, BLE is a different technology). The role of the device depends on the characteristic/profile, that it exposes to the host. There are profiles for HID, Serial, Audio, ... .

The HC-06 is a bluetooth slave device, which acts as a bluetooth-serial-bridge (like the Atmega32u4 acts as a USB-serial-bridge). But this is a software limitation. The HC-06 has standard bluetooth hardware, but the firmware on it just gives you the Serial profile (in fact a HC-06 is mostly the same like the master device HC-05, just different firmware and corresponding breakout boards can break out other pins). So by flashing (programming) it with a different firmware, you can get different profiles. If you find a firmware, that gives you HID functionality, you can flash that to the HC-06 and use it. Though this is a bit hacky I think (haven't done it myself), so it might be a bit too much for a beginner.

**Bluetooth Slave/Master:** The bluetooth protocol uses fixed roles for the two connected devices. One is the master and one is the slave. The master controls, if the communication is really happening. For example a bluetooth headset is a slave device. You cannot connect the bluetooth headset to your bluetooth keyboard, because both are slave devices. You always need one master and one slave. The HC-05 is basically the same module as the HC-06, but it's firmware enables it do be master or slave (configurable by you). So some devices support both modes, but still in any specific connection they can only have one of the modes (need to either master OR slave at any time).

> Anyone know would making that macro pad BT compatible be possible or not ?

Possible, yes. But I suggest you invest in buying a ready to use bluetooth HID controller (immediately found this one from adafruit, though you might might cheaper versions). That will be way easier, than directly jumping into flashing a HC-06. Though that is still a possible path to go.

Another way to go would be to just use the serial functionality and write a small program for your PC, which reads from the Serial interface and issues key strokes according to the serial data. Then you don't need to reflash the HC-06.
> 1 votes

---
Tags: arduino-uno, keyboard, hc-06, hid
---


# Question
Title: is there any real arduino emulators (so I can upload and run machine code on it)
I play with Arduino Micro. I write my programs in directly in machine code, in binary editors (yes, I know that there are more easy ways to program an Arduino, I do it for fun and learning). Often my programs work, but if not, then I would like to run them on an emulator to understand what's exactly going on under the hood. Is there any Arduino emulator that accepts hex files with compiled program and can execute it? I already looked at tools mentioned at Can I program for Arduino without having a real board? , but as far as I see, they are simulators rather than emulators and I can't use compiled binary programs in them.

# Answer
> 3 votes
**Disclaimer**: I have no affiliation with Wokwi (based on opensource AVR8js engine) except that I have learnt a lot from it.

I just tried it on the free Wokwi Arduino simulator(my favourite Arduino simulator for learning) and it worked in a blink!

**Here is what I did to load the hex file into the Arduino simulator**

1. Go to the Arduino IDE and open the basic blink example
2. Change the ON time delay to 100ms (to make sure, the hex file is really loaded into the Arduino simulator and to verify it's working.
3. Once the modified example is compiled go to the `%temp%` folder
4. Search for `*.hex` files and find the one which is just the latest one (this is the only way I found to grab the hex file needed)
5. Go to Wokwi Arduino Simulator with any Arduino example
6. Click on the editor tab in the left
7. Press function key `F1`
8. Select the option `Load HEX file and START simulation`
9. Done - the simulation should run like expected.

I have created a short GIF and I hope you like it (lazy to show step by step)

# Answer
> 1 votes
There are many different processors used in making many different types of Arduino boards. So there is no one way to write Arduino machine code.

There are emulator for simpler processors available for the asking. But, while they work, it is not believe they claim to be totally accurate.

At one point in processor development history, ICE machines were widely used. This is where a real processor is modified to allow access to internal controls and registers. (This actually sounds like the answer to your question.) However, as processors grew in speed and complexity, this approach grew out of favor.

Currently, most processors are built with extra internal circuitry and interface to break program execution for debugging purposes. JTAG is one such industry standard / example.

So, while the question has merit, the common practice is likely not to run code on an emulator, but to run it on the processor using the JTAG interface and an IDE running on a host-computer / work-station.

---
Tags: emulation
---


# Question
Title: Smooth Servo movement for robotic arm: An ongoing answer and soluton
This is not and will not be a duplicate. This is a thread meant to share a solid soliton I figured out with the rest of the community and update it as I optimize it, ad-hoc. So I had visited StackExchange Arduino community to check if there is a better way to make a servo move smoother, since if we assing a new position to a servo that is attached on an arm, it moves like an attacking karateka.

I found these threads:

Smooth servo control library (Dat-ha provided a piece of code that I suggest a correction here)

I also checked this: My Servo Won't Sweep Smoothly

I will self-answer and update this thread, as I make a full arm code working properly and include instructions for the rest of the people to save everyone some time. I still haven't added the capacitor that is suggested on the threads but I will ASAP.

# Answer
Your original solution uses blocking code (the for loops with `delay()` calls in them). Surely that works, but it can easily get you in trouble, when extending the project with more functionalities (since nothing else can be done during the sensor movement). So I would suggest a way to ditch all blocking for loops and delays, so that other code can run during the servo movement. For this we can use `millis()` and the coding principle from the `BlinkWithoutDelay` example, that comes with the Arduino IDE.

```
#include <Servo.h>

Servo servo1;
int set_angle = 0;
int current_angle = 90; // setting starting angle to 90 degrees
unsigned long servo_timestamp = 0;
#define SERVO_INTERVAL    10   // changing the servo position every 10ms, defines the speed of the servo

void setup()
{
    servo1.attach(11);  // connect Servo to pin 11
    pinMode(A0, INPUT); // Connect potentiometer or Joystick x or y pin to A0 input
}

void loop(){
    if(millis()-servo_timestamp > SERVO_INTERVAL){
        servo_timestamp += SERVO_INTERVAL; // increment our timestamp by the servo interval
        // Measure the new set_angle only, if we really want to move the sensor
        int val1 = analogRead(A0); // Read the potentiometer position
        set_angle = map(val1, 0, 1023, 0, 180); // Map the value to be used with servo

        // Increment or decrement the current angle according to the set_angle
        // and don't change it, when we already are at the set_angle
        if(set_angle > current_angle){
            current_angle++;
        } else if(set_angle < current_angle){
            current_angle--;
        }
        // Write the new angle to the servo
        servo1.write(current_angle);
    }
}

```

For learning more about the non-blocking coding style using `millis()`, you can google for it and look at the `BlinkWithoutDelay` example. There are many resources for this on the web. The combination of timestamp and `millis()` if statement executes the code inside the if statement at the regular interval `SERVO_INTERVAL`. There we read the potentiometer and calculate the new setpoint for the servo angle. Then we increment or decrement the current angle by 1 depending on the set angle. And then we write that new angle to the servo.

You can change the speed by either changing `SERVO_INTERVAL` or by in-/decrementing `current_angle` by more than only 1.

The code outside the if statement still runs at full speed. So in the (a bit less than) 10ms, that the servo code isn't running, you can execute other code. Also this code will react immediately, where a blocking code would first let the servo run to the set position and only then change again.

Note: The above code isn't tested. It's purpose is to show the principle. There might be small errors, that I haven't seen.
> 3 votes

# Answer
Here are the simulation results of the code from Chrisl

The code (same as the other answer)

```
#include <Servo.h>

Servo servo1;
int set_angle = 0;
int current_angle = 90; // setting starting angle to 90 degrees
unsigned long servo_timestamp = 0;
#define SERVO_INTERVAL    10   // changing the servo position every 10ms, defines the speed of the servo

void setup()
{
    servo1.attach(11);  // connect Servo to pin 11
    pinMode(A0, INPUT); // Connect potentiometer or Joystick x or y pin to A0 input
}

void loop(){
    if(millis()-servo_timestamp > SERVO_INTERVAL){
        servo_timestamp += SERVO_INTERVAL; // increment our timestamp by the servo interval
        // Measure the new set_angle only, if we really want to move the sensor
        int val1 = analogRead(A0); // Read the potentiometer position
        set_angle = map(val1, 0, 1023, 0, 180); // Map the value to be used with servo

        // Increment or decrement the current angle according to the set_angle
        // and don't change it, when we already are at the set_angle
        if(set_angle > current_angle){
            current_angle++;
        } else if(set_angle < current_angle){
            current_angle--;
        }
        // Write the new angle to the servo
        servo1.write(current_angle);
    }
}

```

You can tweak the code and see the changes online- Link to the arduino simulation
> 2 votes

# Answer
```
  #include <Servo.h>
    Servo servo1;
    int previousangle1;
    int dc;
    void setup()
      {
        dc = 10;    // Delay calibration
        servo1.attach(11);  // connect Servo to pin 11
        pinMode(A0, INPUT); // Connect potentiometer or Joystick x or y pin to A0 input
        previousangle1 = 90; // Initialize position to 90 degrees (180 degree servo)
      }

    void loop()
      {

      int val1 = analogRead(A0); // Read the potentiometer position
      int angle1 = map(val1, 0, 1023, 0, 180); // Map the value to be used with servo

      if(angle1>previousangle1)
      {
        for(int i=previousangle1; i<=angle1; i++)
        {
          servo1.write(i); //turn servo by 1 degrees
          delay(dc);        //delay for smoothness
        }
      }
      // Fix: This needed to be an else if
      // Original piece of code had it as a second stand alone if
      else if(angle1<previousangle1)
      {
        for(int j=previousangle1; j>=angle1; j--)
        {
          servo1.write(j);
          delay(dc);
        }
      }
      delay(dc);
      previousangle1 = angle1;
      }

```

What you need to do now, is make similar code, with different variables for all 4 servos. I still have to check the addition of a capacitor to make it work even better.

Original code is taken from here: https://arduino.stackexchange.com/a/29970/76974

I will edit this, adding code for the rest of the servos later on.
> 0 votes

---
Tags: servo, robotics
---


# Question
Title: How can I run Hello World using Serial Monitor in Tinkercad Arduino simulator?
I want to achieve printing `Hello World` in the serial monitor using Tinkercad to simulate Arduino.

Here is a very simple example code for real Arduino.

```
void setup() {
  // put your setup code here, to run once:
  Serial.begin(9600);
  Serial.println("Hello World!");
}

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

}

```

However, putting an Uno board, typing this code, and clicking "Start Simulation" in Tinkercad doesn't show the `Hello World` message.

Is it doable? If so how?

For real Arduino, you need to select Arduino serial port and open Serial Monitor. But I can't find such an option for Tinkercad. I can't find Serial Monitor in Thinkercad.

My real purpose is to use Serial Monitor output to test code snippets. Right now I don't have real Arduino board with me, so I thought a simulator would be ideal. If I can easily check the values of variables, it doesn't have to be Serial Monitor.

Sorry if this is not a place to ask questions about simulators.

# Answer
I mean where would you expect it to print `Hello World` ... On the Serial Monitor, right? So first open it by clicking on the Serial Monitor button at the bottom of the code tab in Tinkercad.

I tried your code and it works perfectly fine.
> 5 votes

---
Tags: arduino-uno, serial
---


# Question
Title: Code for ESP32 without Development Board
I'm very new to microcontrollers. I'd like to start developing for the esp32, as it has integrated wifi & bluetooth for quite cheap. This being said, i don't have a board yet. Is there a way i can emulate an esp32 board, so i can start programming and debugging my code?

As i'm very new, any advice is welcome.

Thanks

# Answer
> 3 votes
Welcome to Arduino Stack exchange. There are a lot of discussions and half-completed, or project-specific models available for the ESP32 simulator. **My sincere advice is to go ahead and buy real hardware**. By the time you take to set up the simulators (download the repo, set environment variables, connect GDB debugger or other), you would have received the ESP32 hardware itself.

## Why you should go for real hardware?

* An emulator can never match the timing of real ESP32 hardware. if you have any timing-related issue, you cannot fix it using an ESP32 emulator
* Real issues in hardware (bounce/debounce of switches, surge current and brownout voltages, rise time and reflections etc - won't appear in the ESP32 simulators
* EMC issues due to floating inputs, Port pin current limits or even self-heating of components are not considered in most the simulators
* A code running on the emulator can't always run on the real hardware without modifications, especially when it involved multiple threads and priorities

## Still, other options are available online but it depends on your comfort

* ESP32 Simulator by Wokwi \- The ESP32 Simulator is currently in preview (affiliation disclosure)
* ESP32 simulator from mireq \- ESP-IDF contains a small amount of hardware-specific code, FreeRTOS and few multi-platform libraries. This project uses FreeRTOS port for POSIX, LWIP for TCP/IP layer and mbedtls for cryptography functions. In addition, several useful APIs from esp-idf are implemented eg. logging. With this project, you can write a program, which will be runnable and testable on Linux.
* ESP32 machine emulator \- The purpose of this package is to enable you to test-drive (TDD) your MicroPython code in an IDE running on your computer. It seems a lot of people are test-driving python, but not many are test-driving MicroPython. That’s understandable, since many MicroPython projects are simple, and emulating real hardware in a test environment is difficult.
* Bridges \- Pretend your PC a Raspberry Pi or an ESP32 to connect I2C / SPI / GPIO / UART peripherals.

**Note** You should also check when is the last time the projects were updated. The latest ones and active ones are always a better choice as they are expected to have better usability, and stable simulations.

---

A few screenshots from Wokwi ESP32 Simulator

# Answer
> 0 votes
If you are new to microcontrollers then start with basic arduino code and components. Since the esp chips can be coded with the Arduino framework it will be an almost seemless transition from Arduino board to ESP board. Build some circuits on tinkercad.com, write some code, and simulate them. Once you have those basics down hopefully your esp board will have arrived and you can start building your project.

---
Tags: arduino-ide, esp32
---


# Question
Title: How to send int array with ESP8266 http post request?
I'm reading RFID cards' `UID` with an ESP8266 and trying to send that information to my web server hosted on a Raspberry Pi. I'm currently storing the `UID` in an int array, but the `http.POST();` function takes a string input. I tried adding each `UID` digit together, but that doesn't work either.

How would you go about sending the uid in the request?

My code:

```
    /*
    Created by TheCircuit
*/

#define SS_PIN 4  //D2
#define RST_PIN 5 //D1

#include <SPI.h>
#include <MFRC522.h>

#include <ESP8266WiFi.h>
#include <ESP8266HTTPClient.h>
#include <WiFiClient.h>

const char* ssid = "****";
const char* password = "****";
const char* serverName = "****";
int RELAY = 2; //D6

int UIDs[1][4] = {
  {83, 111, 39, 47}
};

MFRC522 mfrc522(SS_PIN, RST_PIN);   // Create MFRC522 instance.

void setup()
{
  Serial.begin(9600);   // Initiate a serial communication
  SPI.begin();      // Initiate  SPI bus
  mfrc522.PCD_Init();   // Initiate MFRC522

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

  WiFi.begin(ssid, password);
  Serial.println("Connecting");
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }
  Serial.println("");
  Serial.print("Connected to WiFi network with IP Address: ");
  Serial.println(WiFi.localIP());
}

boolean compareUIDs(int a[4], int b[4]) {
  for (int i = 0; i < 4; i++) {
    if (a[i] != b[i]) return false;
  }

  return true;
}

void loop()
{
  // Look for new cards
  if ( ! mfrc522.PICC_IsNewCardPresent())
  {
    return;
  }
  // Select one of the cards
  if ( ! mfrc522.PICC_ReadCardSerial())
  {
    return;
  }

  // mfrc522.PICC_DumpToSerial(&(mfrc522.uid));

  int UID[4];
  for (int i = 0; i < 4; i++) {
    UID[i] = mfrc522.uid.uidByte[i];
  }

  Serial.print(UID[0]);
  Serial.print(" ");
  Serial.print(UID[1]);
  Serial.print(" ");
  Serial.print(UID[2]);
  Serial.print(" ");
  Serial.print(UID[3]);
  Serial.println();

  for (int i = 0; i < sizeof(UIDs); i++) {
    boolean success = compareUIDs(UIDs[i], UID);
    if (success) {
      Serial.println("ACCESS GRANTED");
      digitalWrite(RELAY, LOW);

      if (WiFi.status() == WL_CONNECTED) {
        HTTPClient http;

        // Your Domain name with URL path or IP address with path
        http.begin(serverName);

        // Specify content-type header
        http.addHeader("Content-Type", "application/json");

        int httpResponseCode = http.POST("UID GOES HERE");

        Serial.print("HTTP Response code: ");
        Serial.println(httpResponseCode);

        // Free resources
        http.end();
      }

      delay(2000);
      digitalWrite(RELAY, HIGH);
      return;
    }
  }
}

```

# Answer
You could use the (awesome) ArduinoJSON library, but likely overkill for this app. I found it more useful to parse JSON than to construct it.

You could simply print to a buffer and the POST that:

```
char payload[MAX_PAYLOAD];
sprintf(payload, "{\"uid1\":%d,\"uid2\":%d,\"uid3\":%d,\"uid4\":%d}", UID[0], UID[1], UID[2], UID[3]);

http.POST(payload);

```

You would `#define MAX_PAYLOAD` with a value that will be sufficient to hold all the information.

Notice that `sprintf` allows you to use any formatting options you want (e.g. hexadecimal, etc).

If you wanted to send it as an array:

```
sprintf(payload, "{\"uid\":[%d,%d,%d,%d]}", UID[0], UID[1], UID[2], UID[3]);

```
> 1 votes

---
Tags: esp8266, array, rfid, http
---


# Question
Title: What is the maximum wire length for serial communication between two Arduinos?
I am building a project in which two Arduinos will be linked by three wires: TX an RX for serial communication and a common GND. What would be the maximum length of the wires here before communication gets affected?

I am using an Arduino Mega R3 on one side and an Arduino Mini on the other one.

I have no particular requirement for the Baud rate, I could use the lowest one if this helps in any way.

# Answer
You need to specify

* The order of range you are interested in - is it in the order of metres, tens of metres, kilometers or interstate ?:-) . ALL are possible with suitable compromise.
* How you intend to connect to the circuit - direct Arduino pins, high/low buffer, differential drivers, ...

If you use 5V/0V "unipolar" then at say 9600 baud you can get many metres with suitable drivers. If you use an Arduino pin directly wire resistance and inductance will start to matter as range increases.

At 300 baud you can achiever hundreds of metres with twisted pair cables. As range increases aspects like cross-talk from the other circuit and external noise increase in importance. At longer ranges having 4 wires with signal + ground twisted together in each case helps BUT it is likely that at ranges of interest 2 wires plus ground will work OK.

If you are prepared to use enough voltage and slow enough signalling you can signal over thousands of miles - as was done with very early telegraph cables. The thousands of volts needed and signalling speeds of perhaps a few bits per second will be a disincentive in most cases.
> 4 votes

# Answer
This is not exactly what you are asking for but it would be robust and available at low cost in the form of arduino modules. The way I would do it is use a Can Driver and receiver on each end. They are inexpensive differential line drivers. There is nothing that prevents using Async at whatever baud you want up to about 1 megabaud. Run a wire for ground it helps. You will wind up using 5 conductors or 2.5 pairs of wire. Ethernet cable should work fine. You can send some power over the spare wires if you like. You also have the option of using some of the automatic CAN drivers that automatically switch to transmit mode when data is sent and receive otherwise, this will keep you to three wires.
> 0 votes

---
Tags: serial, arduino-mega, arduino-mini
---


# Question
Title: Arduino buzzer code sequence not triggering
I have a problem with my arduino buzzer: the code should be doing the following: I have a security system where in order to open the door you have to enter a 4 digit code from the remote. If the code is correct the door opens. if not you can try again. You have 3 chances to try to enter the pin before an alarm goes on. here comes the problem: the alarms code triggers but the buzzer isn't making any sound.

here is the code for the alarm sound:

```
if (tryCount>=3) { // if the pin is wrong 3 times we sound an alarm
    Serial.println("got in alarm");
    while(true) {
        Serial.println("got in while");
        noTone(buzzer);
        tone(buzzer,100,300);
        delay(300);
        noTone(buzzer);
        tone(buzzer,1000,300);
        delay(300);
    }
}

```

here is the proof the alarm code triggers:

here is the full code: https://create.arduino.cc/editor/mihimbc/8ec2fe30-d812-45cc-b0ae-850b437eb05b/preview

and here is the hardware schematics:

# Answer
The problem was with the buzzer, somehow was a faulty buzzer, I've managed to replace it and the problem was solved. Thanks everybody for your time trying to help me!
> 1 votes

---
Tags: arduino-uno, programming, c, buzzer
---


title: random characters

text:
# Question
Title: random characters
I am using arduino mega with LCD 4X20 character to measure weight by 40 kg load cell and pt 100 to measure the temp. I have 4 output to 4 relay module. all are powered from 12vdc /3 amp Power supply.. the problem is.. the display started normally showing every thing perfectly.. but when the output comes out and the loads runs.. random characters appear is the power supply is not enough? or another problem.. Please advice.

# Answer
Random Characters can Happen in several ways.

* Check the Wires for: Loosen Ends; Broken Wires and Wrong Pin Connections.
* Check your Code.
> 2 votes

# Answer
I'd suspect that it is a software error. Did you check your circuit if it induces desync between the Arduino and the LCD, or did you just use the wrong drivers?
> 1 votes

---
Tags: arduino-mega
---


title: Turning off a LED

text:
# Question
Title: Turning off a LED
I am trying to make 2 alarms for 2 different times using 2 LED's which should turn on when the time corresponds to the set time and then if a pushbutton is pressed, the LED should turn off. For the first alarm, the first LED can be turn off with the pushbutton, instead for the second alarm, the second LED is turning on, but if the pushbutton is pressed is will not turn off, even though is the same code. What can I do to turn off the second LED?

```
#include <RTClib.h>
#include <Wire.h>
#include <LiquidCrystal_I2C.h>
LiquidCrystal_I2C lcd(0x27, 16, 2);
int nowHr, nowMin, nowSec;
RTC_DS3231 rtc;

int h1 = 15;
int m1 = 51;
int h2 = 15;
int m2 = 52 ;
int pin_buton1 = 8;
int stop_buton =9;
int state_stop_buton = 0;

int led1_pin = 6;
int state_led = LOW;
int pushpressed = 0;

int led2_pin = 7;
int state_led2 = LOW;

void setup()
{

  Wire.begin();
  //rtc.adjust(DateTime(F(__DATE__), F(__TIME__)));
  rtc.adjust(DateTime(2021, 03, 27, 15, 50, 50));

  lcd.backlight();
  lcd.begin(16, 2);
  lcd.clear();
  lcd.setCursor(0, 0);
  lcd.print("Welcome To Our");
  lcd.setCursor(0, 1);
  lcd.print("device");

  pinMode(pin_buton1, INPUT);
  pinMode(stop_buton, INPUT);
  pinMode(led1_pin, OUTPUT);
  pinMode(led2_pin, OUTPUT);
  delay(2000);
  Serial.begin(9600);
}

void loop() {
  timeScreen();
  first_alarm();
  stopPins();
  second_alarm();
  stopPins2();

  state_stop_buton = digitalRead(stop_buton);

}

void timeScreen() {

  DateTime now = rtc.now();
  lcd.clear();
  lcd.setCursor(0, 0);
  lcd.print("Time:");
  lcd.setCursor(6, 0);
  lcd.print(nowHr = now.hour(), DEC);
  lcd.print(":");
  lcd.print(nowMin = now.minute(), DEC);
  lcd.print(":");
  lcd.print(nowSec = now.second(), DEC);
  lcd.setCursor(0, 1);
  lcd.print("Date: ");
  lcd.print(now.day(), DEC);
  lcd.print("/");
  lcd.print(now.month(), DEC);
  lcd.print("/");
  lcd.print(now.year(), DEC);
  delay(500);

}

void stopPins() {
  if (state_stop_buton == 1) {

    pushpressed =1;
    lcd.clear();
    lcd.setCursor(0, 0);
    lcd.print("first message ");
    lcd.setCursor(0, 1);
    lcd.print("was read");
    delay(1200);
    lcd.clear();
  }
}

void startBuzz() {

  if (pushpressed == 0) {

    if (state_led == LOW) {
      state_led = HIGH;
      digitalWrite(led1_pin, state_led);

    }
  }
  else if (pushpressed == 1) {

    state_led = LOW;
    digitalWrite(led1_pin, state_led);
  }
}

void first_alarm() {
  DateTime t = rtc.now();
  if (int(t.hour()) == h1 && int(t.minute()) == m1) {

    lcd.clear();
    lcd.setCursor(0, 0);
    lcd.print("first ");
    lcd.setCursor(0, 1);
    lcd.print("text");
    startBuzz();
    delay(5000);

  }
}

//

void stopPins2() {
  if (state_stop_buton == 1) {

    pushpressed = 1;
    lcd.clear();
    lcd.setCursor(0, 0);
    lcd.print("second message ");
    lcd.setCursor(0, 1);
    lcd.print("was read ");
    delay(1200);
    lcd.clear();
  }
}

void startBuzz2() {

  if (pushpressed == 1) {

    if (state_led2 == LOW) {
      state_led2 = HIGH;
      digitalWrite(led2_pin, state_led2);

    }
  }
  else  if (pushpressed == 0 ) {
    state_led2 = LOW;
   digitalWrite(led2_pin, state_led2);
 }
}

void second_alarm() {
  DateTime t = rtc.now();
  if (int(t.hour()) == h2 && int(t.minute()) == m2   ) {

    lcd.clear();
    lcd.setCursor(0, 0);
    lcd.print("second");
    lcd.setCursor(0, 1);
    lcd.print("text");
    startBuzz2();
    delay(5000);

  }
}

```

# Answer
> 3 votes
**1.** `pushpressed` gets set, but never reset.

It's set in `stopPins()` and `stopPins2()` if the input is `HIGH`. Since it's never reset back to zero, once it's been set, the logic in `startBuzz` and `startBuzz2` will follow a single pass. You've created a latched switch.

---

*General Stuff*

---

**2.** Inconsistent naming: makes reading code harder

Pick `snake_case` or `camelCase` or `smashitalltogether` (not recommended) and stick with it :) Same goes for the "types" of variables: some things are named `xxx pin xxx`, some are named `xxx state xxx`, some aren't. It's clearer when same-things are named-same.

**3.** Duplication: makes understanding code harder

Along with the naming, the (essentially) duplicated code makes tracking down problems harder, as you've noticed trying to debug this problem. There are a ton of ways to go about shrinking the code down to make it understandable. The nutshells are to identify the differences in similar code, and to do less at once.

(And if you want to take it to its logical conclusion, wrapping up each alarm in a class would eliminate all duplication and most function parameters :)

---

*Annoying Diversion of Explanation*

---

Let's look at `startBuzz` and `startBuzz2`.

```
void startBuzz() {
  if (pushpressed == 0) {
    if (state_led == LOW) {
      state_led = HIGH;
      digitalWrite(led1_pin, state_led);
    }
  } else if (pushpressed == 1) {
    state_led = LOW;
    digitalWrite(led1_pin, state_led);
  }
}

void startBuzz2() {
  if (pushpressed == 1) {
    if (state_led2 == LOW) {
      state_led2 = HIGH;
      digitalWrite(led2_pin, state_led2);
    }
  } else if (pushpressed == 0) {
    state_led2 = LOW;
    digitalWrite(led2_pin, state_led2);
  }
}

```

The only things different here are the LED pin, and the LED state. Let's normalize our naming so things become clear, using `startBuzz` as the example. We'll also assume `pushPressed` can only be 0 or 1 (HIGH or LOW):

```
void startBuzz() {
  if (pushPressed == LOW) {
    if (led1State == LOW) {
      led1State = HIGH;
      digitalWrite(led1Pin, led1State);
    }
  } else {
    led1State = LOW;
    digitalWrite(led1Pin, led1State);
  }
}

```

We can make this work for either LED by doing two things: taking in the pin and current state, and returning the new state. Why return the new state instead of setting it here? It makes the mainline code easier (and avoids passing a reference).

```
void startBuzz(int ledPin, int ledState) {
  int newLedState = ledState;

  if (pushPressed == LOW) {
    if (ledState == LOW) {
      newLedState = HIGH;
      digitalWrite(ledPin, newLedState);
    }
  } else {
    newLedState = LOW;
    digitalWrite(ledPin, newLedState);
  }

  return newLedState;
}

```

Then when we call `startBuzz` or `startBuzz2` we replace the current code with:

```
led1State = startBuzz(led1Pin, led1State);

```

We're not done.

Since we keep the original `ledState` we can remove the duplicated calls to `digitalWrite`; at worst we'll have a superfluous write when `pushPressed != LOW && ledState != HIGH`.

Since all conditions except one lead to a `LOW` value we don't even need to keep the original state. And since it's two conditions to flip it `HIGH` we can combine those. And if we pull out the digitalWrite we're really just calculating the next state--that doesn't rely on the LED pin.

```
void getNextLedState(int ledState) {
  return (pushPressed == LOW && ledState == LOW) ? HIGH : LOW;
}

```

And the callsites look like this:

```
led1State = getNextLedState(led1State);
digitalWrite(led1Pin, led1State);

```

Similarly for the alarms: create a function called `checkAlarm` that takes in hrs and mins and returns a boolean. In the loop call `checkAlarm(h1, m1)` and if true, call `runAlarm1()`. (Even that could be shrunk further, but you get the idea.) `stopPins` differs only in the strings written to the LCD. And so on.

---
Tags: led, switch, ds3231-alarms
---


# Question
Title: HTTPS GET request working on esp32 but not on esp8266
I'm trying to port my esp32 program to esp8266, and i've come across a problem where i can't get a response from a HTTPS GET request on esp8266, but on my esp32 the same code works fine. The function i'm using looks like this:

```
void GetHTTP()
{
  if (WiFi.status() == WL_CONNECTED)
  {
    HTTPClient http;
    http.begin(requestURL);
    int httpCode = http.GET();
    if (httpCode > 0)
    {
      requestData = http.getString();
      GenerateTable();
      //GetDelimiterCount(requestData, delimiterStart);
    }
    http.end();
  }
}

```

I've also tried running my request with the esp8266 "BasicHttpsClient" and "BasicHttpClient", and in both cases the program returns the error: "connection failed" from `https.errorToString(httpCode).s_str()` or http code "-1" without any API specific error codes.

I'm requesting from Trafiklab's realtime infromation v4 API And the request looks somewhat like this:

> https://api.sl.se/api2/realtimedeparturesV4.json?

I've omitted the API key and parameters i use from this URL. The response is also correct when requested by any browser.

Could this be something to do with SSL? I'm completely out of clues as to what the differences between esp32's and esp8266's http-client libraries might be. I'm also using the latest version of the ESP8266 Boards libraries (2.7.4).

# Answer
I ended up using

> ESP8266WiFi.h

instead of

> ESP8266WiFiMulti.h

This fixed both my original code and the basic HTTPS example. I still don't understand what difference it made though.
> 0 votes

---
Tags: esp8266, esp32, http, web-service
---


# Question
Title: error: expected primary-expression before ',' token edit status 1
Im using tinkercad for my robotics class and I can't seem to figure out a solution for this problem. Heres my codes:

```
#include <LiquidCrystal.h> //LCD library
#define echo 2
#define trig 3

// Gas Sensor
#define GREEN 4
#define Yellow 6
#define RED 7
#define Buzzer 5
#define Sensor A0

float duration;
float distance;

LiquidCrystal lcd(13,,12,11,10,9,8);

int sensor_Input;
float temp;

void setup()
{
  // Ultrasonic sensor
  pinMode(trig, OUTPUT);
  pinMode(echo, INPUT);
  Serial.begin(9600);
  lcd.begin(13, 2);

  //temp
  measure_Temp();
  display_Temp();

  // Gas Sensor
  for (int i = 0; i < 6; i++)
    pinMode(i, OUTPUT);
  Serial.begin(9600);
}

void loop()
{
  // Ultrasonic Sensor
  time_Measurement();
  distance = duration * (0.0343) /2;

  display_distance();

  // Gas Sensor
  for (int i = 0; i < 6; i++)
    digitalWrite(i, LOW);

  status_Indicator();
}

void status_Indicator()
{
  // Gas Sensor
  int sensor_In = analogRead(A0);
  Serial.println(sensor_In);

  if ( sensor_In>=40 )
  {
    digitalWrite(RED, HIGH);
    digitalWrite(Buzzer, HIGH);
  }
  else if (sensor_In >=25 )
  {
    digitalWrite(Yellow, HIGH);
  }
  else
  {
    digitalWrite(GREEN, HIGH);
  }
  delay(10);
}

void time_Measurement()
{
  // Ultrasonic Sensor
  digitalWrite(trig, LOW);
  delayMicroseconds(2);

  digitalWrite(trig, HIGH);
  delayMicroseconds(10);
  digitalWrite(trig, LOW);

  duration = pulseIn(echo, HIGH);
}

void display_distance()
{
  lcd.clear();
    lcd.setCursor(0, 0);
  Serial.print("Distance in m: ");
  Serial.print(distance);
  Serial.println();
  lcd.print("distance in m: ");
  lcd.setCursor(5, 1);
  lcd.print(distance);
  delay(1000);
}

void measure_Temp()
{
  //Temp
  sensor_Input = analogRead(A0);
  temp = (float)sensor_Input / 1024;
  temp = temp *5;
  temp = temp - 0.5;
  temp = temp *100;
}

void display_Temp()
{
  //temp
  lcd.setCursor(0, 0);
  Serial.print("Temp. in Celcius: ");
  Serial.print(temp);
  Serial.println();
  lcd.print("Temp. in Celcius: ");
  lcd.setCursor(5, 1);
  lcd.print(temp);
  delay(500);
}

```

# Answer
You have two commas in the command when making the `lcd` object:

```
LiquidCrystal lcd(13,,12,11,10,9,8);

```

Probably just a typo, delete the comma and you should be good to go.

```
LiquidCrystal lcd(13,12,11,10,9,8);

```
> 2 votes

---
Tags: error
---