title: PCA9685: how "unset" PWM signal?

text:
# Question
Title: PCA9685: how "unset" PWM signal?
I use my Arduino with Adafruit PCA9685 servo controller. To set PWM signals I use the provided library: https://github.com/adafruit/Adafruit-PWM-Servo-Driver-Library

It allows easily set PMM signal and works good. But how can I "unset" PWM signal for a certain pin?

If a PWM siganl is active, the servo stucks on the current position and can't be moved by hand, but only by setting other pulse length. So I need to move servo and then "free" it.

# Answer
> 3 votes
You can try to send no "ON" time to your output pin on the PCA9685. So, you start the "ON" at 0 and stop the "OFF" at 0.

```
void freeServo(uint8_t servoIdx)
{
  pwm.setPWM(servoIdx, 0, 0 );
}

```

# Answer
> 0 votes
You could try changing the corresponding pin from output to input. To be sure not to disturb other comfigurations you could do direct port manipulation.

```
void servo_off() {
  DDRD &= ~(1<<PD5);
}

void servo_on() {
  DDRD |= (1<<PD5);
}

```

This assumes you use pin PD5 for the pwm signal. Adjust the "D" in DDR**D** and P**D**5 so it matches the port in use as well as the pin number.

Of course, you need some additional user input like a button to trigger calls to those functions.

# Answer
> 0 votes
Are your servo's control pins active high or active low?

From the library code at https://github.com/adafruit/Adafruit-PWM-Servo-Driver-Library/blob/d265f74fc0e66632e6dafc787c95b008f3245550/Adafruit\_PWMServoDriver.cpp#L242 it looks like there are special on&off values of `setPWM(pin,on,off)` that turn the servo fully on or fully off, and how they work they depends on whether the servo pin is active high or active low.

```
unsigned byte idle = CertainPin;

servoController01.setPWM(idle, 0, 4096); // fully off Active high
// servoController01.setPWM(idle, 4096, 0); // fully off Active low

```

or with the better documented `setPin()`:

```
servoController01.setPin(idle,0,false); // Active high
//servoController01.setPin(idle,0,true); // Active low

```

# Answer
> -1 votes
Unluckily, AFAIK, the servo powers the motor even when the PWM signal is not applied. So "removing" the PWM is useless.

You will have to "turn off" the servo by removing the power. To do this, use a transistor (usually servos are more current-hungry than arduino can bear). When you want to "free" the servo, remove the power and it will be "free".

# Answer
> -1 votes
I got same problem, searched around but found no answer, so I looked into the source code and found that you simply have to set the angle of the servo to 'None' to stop sending PWM pulses to the servo. For example, if your servo uses channel 14 on the PCA9685 board:

kit.servo\[14\].angle = None

---
Tags: arduino-due, servo
---


# Question
Title: Can arduino show the power drawn from its output pin on serial monitor? If yes, what code should I use?
I want to know is it possible that arduino can show how much power my prototype is drawing from arduino and if it can what would be the code for that.

# Answer
> 5 votes
You cannot directly measure the power, no. But it's simple enough to arrange using a very small amount of extra hardware.

Depending on what the device is you want to monitor there are two ways of creating the circuit that you need. Both require just a single small resistor, and either one or two analog pins.

The simplest arrangement is the "low-side current shunt" and is simply a small resistor between the ground of your device and the ground of the Arduino. This causes a small voltage drop which raises the ground potential of your device slightly, so could have an effect on communication if you're not careful (see the alternative below). Then a connection from the "top" of that resistor to an analog input will allow you to monitor the voltage drop across that resistor. From that, using Ohm's Law, you can calculate the current. That then can give you the power.

Here's a schematic:

simulate this circuit – Schematic created using CircuitLab

This arrangement does have the benefit that it will work for any power supply voltage, not just the 5V supply pin (for example powering from the VIN pin or 3.3V pin).

If you are powering your device from no more than 5V you can place the resistor in the 5V feed and avoid the offset to the ground voltage. The idea is just the same: use an analog input to monitor the voltage drop across the resistor to calculate the current and hence the power:

simulate this circuit

If you want to measure the current being drawn out of a GPIO pin, though, there is an extra step you need to consider. The GPIO has a MOSFET within it which imposes a small resistance of its own on the output. This resistance will of course cause a variation in the output voltage depending on the current drawn from the output pin. So it is important to know what the actual output voltage is rather than assuming that it would be 5V. For that a second analog input is needed:

simulate this circuit

Now the voltage drop is calculated as the difference between the voltages measured by A0 and A1. Then all the other calculations are the same.

# Answer
> 1 votes
No, it cannot do power measurement. With an Arduino (and most other microcontrollers) you only have voltage measurement (on the analog input pins).

Though this is half of the power measurement, since power is voltage multiplied by current. Measure the voltage on that pin with an analog pin. Then you need a way to measure the current. For that you need extra hardware. There are current sensors made for Arduino, which measure the current flowing through its pins and giving out a corresponding analog voltage, which you can then measure on an analog pin. Make sure that the current sensor is rated for the correct current range to not overload it or loose resolution (by having a way bigger range in the sensor than with the actual current). For a digital output pin of an Arduino Uno/Nano the max. current should be 20mA.

You can also google for something like "Arduino current sensor". A short search gave me some promising results.

Then when you have measured the voltage and current you can multiply them to get the power.

---
Tags: arduino-uno, power
---


# Question
Title: How to detect Arduino serial port programmatically on different platforms?
I am trying to write a little program that needs to detect Arduino ports automatically. I have tried many methods but haven't found any reliable way.

I can see that the Arduino IDE can detect it, by showing `/dev/cu.xyz (Arduino Uno)` or `COM6 (Arduino Uno)` etc.

How could I detect if the device connected to the serial port is an Arduino or not? Preferably without pre-flashing the Arduino with specific firmware.

I found this Python version, which uses `serial.tools.list_ports.comports()` here, but it didn't work when I tested it on Windows and MacOS.

The best I can get is by using go-serial's `USBManufacturer`, I can get 'Arduino (www.arduino.cc)'.

I also found this post, about the same question, but without any solution.

# Answer
> 2 votes
Quite late for the party! Just leave it here for anyone looking for a solution on windows.

The proper way is to read the device list from registry.

First location is

> ***HKEY\_LOCAL\_MACHINE\HARDWARE\DEVICEMAP\SERIALCOMM***

A better location is here

> ***HKLM\SYSTEM\CurrentControlSet\Services\usbser\Enum***

You have the list of Arduino devices there. Mine is Arduino Leonardo. Genuine Arduino UNO uses the similar chip and it should be in there as well.

To get the port, just copy the first device (index 0) and plug into this location

> ***HKLM\SYSTEM\CurrentControlSet\Enum***

So it is like this

> ***HKLM\SYSTEM\CurrentControlSet\Enum\USB\VID\_2341&PID\_8036&MI\_00\9&88cb209&0&0000***

So you have friendly name and port number of the serial device. Then just write some code to read these registry locations.

In C

```
#include <windows.h>
#include <wchar.h>
#define MAX_VALUE_LENGTH 255

void getUSBSerialList()
{

    HKEY hKey;
    //check if we can read registry
    INT dwRegOPenKey = RegOpenKeyEx(HKEY_LOCAL_MACHINE, _T("SYSTEM\\CurrentControlSet\\Services\\usbser\\Enum"), 0, KEY_READ, &hKey);
    if(dwRegOPenKey != ERROR_SUCCESS) return 0;

    DWORD type=REG_DWORD, size=0, USBser_count = 0; // a place for RegQueryValueEx to write back to
    DWORD dwRes;

    //read count of usb devices
    dwRes = RegQueryValueExW(hKey, _T("Count"), NULL, (LPDWORD) &type, (LPBYTE) &USBser_count, &size);
    if (dwRes) return 0;

    if (USBser_count)
    {
        for (INT i=0, dwRes = ERROR_SUCCESS; i<USBser_count; i++)
        {
            WCHAR achValue[MAX_VALUE_LENGTH];
            WCHAR buffer[MAX_VALUE_LENGTH];
            ZeroMemory(buffer, sizeof WCHAR  * MAX_VALUE_LENGTH);

            swprintf(achValue, L"%d",i); // read value name "0", "1"...
            dwRes = RegQueryValueExW(hKey, achValue, NULL, (LPDWORD) &type, (LPBYTE) &buffer, &size);

            // Plug that value into "SYSTEM\\CurrentControlSet\\Enum\\"
            HKEY hKey2;
            swprintf(achValue, L"SYSTEM\\CurrentControlSet\\Enum\\%s",buffer);

            INT dwRegOPenKey2 = RegOpenKeyExW(HKEY_LOCAL_MACHINE, achValue, 0, KEY_READ, &hKey2);
            if (dwRegOPenKey2) return 0; // check if this key exists

            // From here read friendly name
            dwRes = RegQueryValueExW(hKey2, _T("FriendlyName"), NULL, (LPDWORD) &type, (LPBYTE) &buffer, &size);
            if (dwRes) return 0;

            // or read COM port
            swprintf(achValue, L"%s\\Device Parameters", achValue);
            dwRegOPenKey2 = RegOpenKeyExW(HKEY_LOCAL_MACHINE, achValue, 0, KEY_READ, &hKey2);
            if (dwRegOPenKey2) return 0;

            dwRes = RegQueryValueExW(hKey2, _T("PortName"), NULL, (LPDWORD) &type, (LPBYTE) &buffer, &size);
            if (dwRes) return 0;
        }
    }
}

```

In C#, just use Registry object to do so

```
int usbser_count = (int)Registry.GetValue("HKEY_LOCAL_MACHINE\\SYSTEM\\CurrentControlSet\\Services\\usbser\\Enum", "Count", -1);

```

I haven't done it in C# but I think it's easier than in C.

What if yours is arduino clone that use CH340 instead of atmega16u2, it won't appear in the registry location above. It will show up here instead:

> ***HKEY\_LOCAL\_MACHINE\SYSTEM\CurrentControlSet\Services\CH341SER\_A64\Enum***

You can do the same for other type of USB serial devices like CP210x (on some ESP32 dev boards)

> ***HKEY\_LOCAL\_MACHINE\SYSTEM\CurrentControlSet\Services\silabser\Enum***

Or even get a list of WinUSB devices (such as ST-Link v2)

> ***HKEY\_LOCAL\_MACHINE\SYSTEM\CurrentControlSet\Services\WINUSB\Enum***

# Answer
> 1 votes
Here is a solution:

On Windows, Arduino IDE comes with a tool named **listComPorts.exe**, which will list all COM ports and their USB info like VID & PID. There is also a file named **arduino.inf** in drivers folder contains all known device types and their VID&PID etc, and we can look for the connected device.

On \*nix, the IDE take advantage of libusb and no such a tool, and it's easy to find a tool to list usb info on these platforms.

This go package mentioned in the question is a good choice, which also uses libusb and could build on all platforms. (On windows, you have to install mingw to build the C code, cygwin & msys don't work, I tried TDM-GCC and it works. You also have to add `LDFLAGS: -lsetupapi` (in serial.go) to successfully link the code.) After list all serial ports, you can search for 'Arduino' to determine the port. 'CH340' is also a keyword to search as many modified boards use this chipset.

New version of the IDE don't have **listComPorts.exe**, they all uses libusb. I find this tool from version 1.6.5.

# Answer
> 0 votes
You can start the Arduino IDE wait unit the port is detected-which are stored on the hard drive by the arduino IDE;exit the IDE; then read through that file with your custom Windows (or whatever OS you're using -to get your answer. This answers your question you wrote above.

# Answer
> 0 votes
Here is snippet of C# code based on answer by SimonVu14. It looks through the named keys and gets ports for both Atmega and CH340 chips. If you expect to have just one Arduino connected to the computer, you can just go with the first one found. Otherwise you'll need to invent something to figure out which one is yours (which usually involves opening port, sending some predefined request and expecting some predefined response), or give user option to select via UI.

```
    private readonly string[] _arduinoKeys = {
        @"HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\usbser\Enum",
        @"HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\CH341SER_A64\Enum"
    };

    /// <summary>
    /// See https://arduino.stackexchange.com/questions/30808/how-to-detect-arduino-serial-port-programmatically-on-different-platforms/80887
    /// </summary>
    private IEnumerable<(string name, string port)> EnumerateArduinos()
    {
        foreach (var arduinoKey in _arduinoKeys)
        {
            var countObject  = Registry.GetValue(arduinoKey, "Count", null);
            if (countObject is not int count)
            {
                continue;
            }

            for (int i = 0; i < count; i++)
            {
                var enumObject = Registry.GetValue(arduinoKey, i.ToString(), null);
                if (enumObject is not string enumKey)
                {
                    continue;
                }

                var friendlyName = Registry.GetValue($@"HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Enum\{enumKey}", "FriendlyName", null);
                var portName = Registry.GetValue($@"HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Enum\{enumKey}\Device Parameters", "PortName", null);
                if (portName is string port && friendlyName is string name)
                {
                    yield return (name, port);
                }
            }
        }
    }

```

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


# Question
Title: I have been having a lot of trouble adding a countdown to a piece of code
This is the code. The /// are where I added the countdown. Unfortunately the countdown only goes down 9 seconds. What I want it to do is go down the full 24 hours. I have been trying to fix this error for months with no luck.

```
int beeper_pin      = 2; //Naming buzzer pin
int resetGarden_pin = 3; //Naming the warning led pin
int pump_pin        = 6; //Naming the pump pin

#include <LiquidCrystal_I2C.h> // Driver Library for the LCD Module

LiquidCrystal_I2C lcd(0x27, A4, A5);

void clearLCDLine(int line)
{
  lcd.setCursor(0, line);
  for (int n = 0; n < 20; n++) // 20 indicates symbols in line. For 2x16 LCD write - 16
  {
    lcd.print(" ");
  }
}

void beepWarning() {            //Makes beeping a subroutine

  lcd.setCursor(0, 0);
  lcd.print("WARNING");
  delay(100);
  lcd.setCursor(0, 1);
  for (int x = 0; x < 3; x++) {

    lcd.setCursor(0, 1);
    lcd.print("WATER PUMP ACTIVE");
    delay(100);
    clearLCDLine(1);
    lcd.setCursor(0, 1);
    lcd.print("WATER PUMP ACTIVE.");
    delay(100);
    clearLCDLine(1);
    lcd.setCursor(0, 1);
    lcd.print("WATER PUMP ACTIVE..");
    delay(100);
    clearLCDLine(1);
    lcd.setCursor(0, 1);
    lcd.print("WATER PUMP ACTIVE...");
    delay(100);
    clearLCDLine(1);
  }

  lcd.setCursor(0, 1);
  lcd.print("WATER PUMP ACTIVE...");

  for (int x = 0; x < 3; x++) {   //Repeats 3 times

    digitalWrite(beeper_pin, HIGH); //Turn on buzzer
    delay(100);                     //Delay of 400 milliseconds
    digitalWrite(beeper_pin, LOW);  //Turns off buzzer
    delay(100);                     //Delay of 400 milliseconds

  }
}

void SOSWarning() {            //Makes SOS a subroutine

  clearLCDLine(1);
  lcd.setCursor(0, 0);
  lcd.print("WPA Reset Aerogarden");

  for (int x = 0; x < 3; x++) {   //Repeats 3 times

    for (int d = 0; d < 3; d++) {   //Repeats 3 times
      digitalWrite(beeper_pin, HIGH); //Turn on buzzer
      delay(200);                     //Delay of 400 milliseconds
      digitalWrite(beeper_pin, LOW);  //Turns off buzzer
      delay(200);                     //Delay of 400 milliseconds
    }

    for (int a = 0; a < 3; a++) {   //Repeats 3 times
      digitalWrite(beeper_pin, HIGH); //Turn on buzzer
      delay(400);                     //Delay of 400 milliseconds
      digitalWrite(beeper_pin, LOW);  //Turns off buzzer
      delay(400);                     //Delay of 400 milliseconds
    }

    for (int d = 0; d < 3; d++) {   //Repeats 3 times
      digitalWrite(beeper_pin, HIGH); //Turn on buzzer
      delay(200);                     //Delay of 400 milliseconds
      digitalWrite(beeper_pin, LOW);  //Turns off buzzer
      delay(200);                     //Delay of 400 milliseconds
    }

    delay(500);                     //Delay of 500 milliseconds
  }
}

void weekDelay() { //Makes waiting for a week a subroutine
  clearLCDLine(1);
  lcd.setCursor(0, 0);
  lcd.print("Waiting One Week");

long hour = 23, minute = 59, second = 59;//second //////////////////////////
long countdown_time = (hour * 3600) + (minute * 60) + second; ///////////////////////////////////////////////////////////////////////////

  long countdowntime_seconds = countdown_time - (millis() / 1000); /////////

  if (countdowntime_seconds >= 0) {   ///////////////////////////////////////////////
    long countdown_hour = countdowntime_seconds / 3600;
    long countdown_minute = ((countdowntime_seconds / 60) % 60);
    long countdown_sec = countdowntime_seconds % 60;
    lcd.setCursor(4, 1);
    if (countdown_hour < 10) {
      lcd.print("0");
    }
    lcd.print(countdown_hour);
    lcd.print(":");
    if (countdown_minute < 10) {
      lcd.print("0");
    }
    lcd.print(countdown_minute);
    lcd.print(":");
    if (countdown_sec < 10) {
      lcd.print("0");
    }
    lcd.print(countdown_sec);
  }
  delay(500);///////////////////////////////////////////////////////////////

  delay(500);

  delay(86400000);
  clearLCDLine(0);
  lcd.setCursor(0, 0);
  lcd.print("Waiting Six Days");
  delay(86400000);
  clearLCDLine(0);
  lcd.setCursor(0, 0);
  lcd.print("Waiting Five Days");
}

void pumpOn() {               //Makes turning on the pump a subroutine
  clearLCDLine(1);
  lcd.setCursor(0, 1);
  lcd.print("PUMPING");
  delay(100);
  digitalWrite(pump_pin, HIGH); //Turning on the pump
}

void pumpOff() {              //Makes turning off the pump a subroutine
  digitalWrite(pump_pin, LOW);  //Turning off the pump
  clearLCDLine(1);
  lcd.setCursor(0, 1);
  lcd.print("WATER PUMP OFF");
  delay(100);
}

void setup() {
  //run once:
  lcd.backlight();
  lcd.init();

  lcd.setCursor(4, 0);//////////////////////////////////////////////////////
  lcd.print("HH:MM:SS"); //////////////////////////////////////////////////

  lcd.clear(); // Clear the screen
  lcd.setCursor(0, 0);
  lcd.print("Aero_Pump V3");
  delay(1000);
  lcd.setCursor(0, 1);
  lcd.print("By Alex");
  delay(1000);
  pinMode (beeper_pin,      OUTPUT); //Setting outputs
  pinMode (resetGarden_pin, OUTPUT); //Setting outputs
  pinMode (pump_pin,       OUTPUT); //Setting outputs
  lcd.clear(); // Clear the screen

  digitalWrite(resetGarden_pin, LOW); //Turning off the reset garden light

  beepWarning(); //Beeps a warning
  pumpOn();      //Turns on the pump
  delay(3000);  //Adds a delay of 24000 milliseconds
  pumpOff();     //Turns off the pump
  weekDelay();   //Waits a week

  beepWarning(); //Beeps a warning
  pumpOn();      //Turns on the pump
  delay(135000);  //Adds a delay of 48000 milliseconds
  pumpOff();     //Turns off the pump
  weekDelay();   //Waits a week
}

void loop() {

  SOSWarning(); //Beeps an SOS warning
  pumpOn();      //Turns on the pump
  delay(48000);  //Adds a delay of 48000 milliseconds
  pumpOff();     //Turns off the pump

  for (int x = 0; x < 3024000; x++) {
    lcd.backlight(); // turn on backlight.
    delay(100);
    lcd.noBacklight(); // turn off backlight
    delay(100);
  }
  lcd.backlight(); // turn on backlight.
}

```

This is more specifically what needs to be fixed:

```
long hour = 23, minute = 59, second = 49;//second //////////////////////////
long countdown_time = (hour * 3600) + (minute * 60) + second; ///////////////////////////////////////////////////////////////////////////

  long countdowntime_seconds = countdown_time - (millis() / 1000); /////////

  if (countdowntime_seconds >= 0) {
    long countdown_hour = countdowntime_seconds / 3600;
    long countdown_minute = ((countdowntime_seconds / 60) % 60);
    long countdown_sec = countdowntime_seconds % 60;
    lcd.setCursor(4, 1);
    if (countdown_hour < 10) {
      lcd.print("0");
    }
    lcd.print(countdown_hour);
    lcd.print(":");
    if (countdown_minute < 10) {
      lcd.print("0");
    }
    lcd.print(countdown_minute);
    lcd.print(":");
    if (countdown_sec < 10) {
      lcd.print("0");
    }
    lcd.print(countdown_sec);
  }

```

This is some edited code that I have tried but might have made a mistake on because it does 0 days instead of 7 and (Hours/Min/Sec) 04:09:36.

```
void weekDelay() { //Makes waiting for a week a subroutine
  clearLCDLine(1);
  clearLCDLine(0);
  lcd.setCursor(0, 0);
  lcd.print("Waiting One Week");

  unsigned long start = millis();
  unsigned long week_secs = 7 * 24 * 3600;
  unsigned long countdowntime_seconds;

  while (countdowntime_seconds = week_secs - (millis() - start)/1000){
     char buff[80];
     unsigned long countdown_day = countdowntime_seconds / 3600 / 24;
     int countdown_hour = (countdowntime_seconds / 3600) % 24;
     int countdown_minute = ((countdowntime_seconds / 60) % 60);
     int countdown_sec = countdowntime_seconds % 60;
     sprintf(buff,"%1d days, %02d:%02d:%02d",
            (int) countdown_day,
            countdown_hour,
            countdown_minute,
            countdown_sec
            );
     Serial.print(buff);
     clearLCDLine(1);
     lcd.setCursor(2, 1);
     lcd.print(buff);
     delay(1000);
     }
}

```

# Answer
I'd try something with a `while(){}` loop and a `sprintf()`, like:

```
void weekDelay() { //Makes waiting for a week a subroutine
  unsigned long start = millis();
  unsigned long week_secs = 7 * 24 * 3600;
  unsigned long countdowntime_seconds;

  while (countdowntime_seconds = week_secs - (millis() - start)/1000){
     char buff[80];
     unsigned long countdown_day = countdowntime_seconds / 3600 / 24;
     // or maybe
     //int  countdown_day = (int)(countdowntime_seconds / 3600UL / 24UL);

     int countdown_hour = (countdowntime_seconds / 3600) % 24;
     int countdown_minute = ((countdowntime_seconds / 60) % 60);
     int countdown_sec = countdowntime_seconds % 60;
     sprintf(buff,"%1d days, %02d:%02d:%02d",
            (int) countdown_day,
            countdown_hour,
            countdown_minute,
            countdown_sec
            );
     clearLCDLine(1);
     lcd.setCursor(0, 0);
     lcd.print(buff);
     delay(1000);
     }
}

```

Or make it more general and start it off like:

```
void coundownDelay(unsigned long seconds) { //Makes waiting for a week a subroutine
  unsigned long start = millis();
  unsigned long countdowntime_seconds;

  while (countdowntime_seconds = seconds - (millis() - start)/1000){

     ...

}

```

and call like:

```
  ...
  countdownDelay(7 * 24 * 3600);   //Waits a week
  ...

```
> 0 votes

---
Tags: programming, arduino-nano, lcd, timers, code-review
---


# Question
Title: Serial connection between arduino and processing doesn't work; Port busy
I'm trying to connect arduino and processing via serial. Whenever I run the processing sketch I get the following error in Processing:

```
RuntimeException: Error opening serial port COM26: Port busy
Could not run the sketch (Target VM failed to initialize).

```

Below is the arduino sketch and processing code, which I "borrowed" from here, to try to programmatically find the correct serial port to connect to.

Arduino:

```
int var;

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

void loop() {
  if (Serial.available()) {
    var = Serial.read();
  }
  Serial.println(var);
  delay(100);
}

```

Processing:

```
import processing.serial.*;

Serial ser_port;                // for serial port
PFont fnt;                      // for font
int num_ports;
boolean device_detected = false;
String[] port_list;
String detected_port = "";

void setup() {
  size(400, 200);                         // size of application window
  background(0);                          // black background
  fnt = createFont("Arial", 16, true);    // font displayed in window

  println(Serial.list());

  // get the number of detected serial ports
  num_ports = Serial.list().length;
  // save the current list of serial ports
  port_list = new String[num_ports];
  for (int i = 0; i < num_ports; i++) {
    port_list[i] = Serial.list()[i];
  }
}

void draw()
{
  background(0);
  // display instructions to user
  textFont(fnt, 14);
  text("1. Arduino or serial device must be unplugged.", 20, 30);
  text("   (unplug device and restart this application if not)", 20, 50);
  text("2. Plug the Arduino or serial device into a USB port.", 20, 80);

  // see if Arduino or serial device was plugged in
  if ((Serial.list().length > num_ports) && !device_detected) {
    device_detected = true;
    // determine which port the device was plugged into
    boolean str_match = false;
    if (num_ports == 0) {
      detected_port = Serial.list()[0];
    } else {
      // go through the current port list
      for (int i = 0; i < Serial.list().length; i++) {
        // go through the saved port list
        for (int j = 0; j < num_ports; j++) {
          if (Serial.list()[i].equals(port_list[j])) {
            break;
          }
          if (j == (num_ports - 1)) {
            str_match = true;
            detected_port = Serial.list()[i];
          }
        }
      }
    }
  }
  // calculate and display serial port name
  if (device_detected) {
    text("Device detected:", 20, 110);
    textFont(fnt, 18);
    text(detected_port, 20, 150);
    ser_port = new Serial(this, detected_port, 9600);
  }
}

```

I am a newbie at this, so not sure what I'm doing wrong. Would appreciate any help :)

# Answer
I tried your Processing sketch, and it does detect and try to connect to the serial port, but fails for some reason.

Processing "code" can include a `try catch` block to help you diagnose the issue. Using this modified sketch, you can print the errors to the console window.

```
import processing.serial.*;

Serial ser_port;                // for serial port
PFont fnt;                      // for font
int num_ports;
boolean device_detected = false;
String[] port_list;
String detected_port = "";

void setup() {
  size(400, 200);                         // size of application window
  background(0);                          // black background
  fnt = createFont("Arial", 16, true);    // font displayed in window

  println(Serial.list());

  // get the number of detected serial ports
  num_ports = Serial.list().length;
  // save the current list of serial ports
  port_list = new String[num_ports];
  for (int i = 0; i < num_ports; i++) {
    port_list[i] = Serial.list()[i];
  }
}

void draw()
{
  background(0);
  // display instructions to user
  textFont(fnt, 14);
  text("1. Arduino or serial device must be unplugged.", 20, 30);
  text("   (unplug device and restart this application if not)", 20, 50);
  text("2. Plug the Arduino or serial device into a USB port.", 20, 80);

  // see if Arduino or serial device was plugged in
  if ((Serial.list().length > num_ports) && !device_detected) {
    device_detected = true;
    // determine which port the device was plugged into
    boolean str_match = false;
    if (num_ports == 0) {
      detected_port = Serial.list()[0];
    } else {
      // go through the current port list
      for (int i = 0; i < Serial.list().length; i++) {
        // go through the saved port list
        for (int j = 0; j < num_ports; j++) {
          if (Serial.list()[i].equals(port_list[j])) {
            break;
          }
          if (j == (num_ports - 1)) {
            str_match = true;
            detected_port = Serial.list()[i];
          }
        }
      }
    }
  }
  else{
    text("else", 20, 110);
  }
  // calculate and display serial port name
  if (device_detected) {
    text("Device detected:", 20, 110);
    textFont(fnt, 18);
    text(detected_port, 20, 150);
    try{
      ser_port = new Serial(this, detected_port, 9600);
    }
    catch(Exception e){
      // Print detailed error information to the console.
      System.err.println(e);
      e.printStackTrace();
    }
  }
  else{
    text("Device NOT detected:", 20, 140);
  }
}

```

These are the errors I get on my computer using a Arduino Uno.

```
    at processing.serial.Serial.<init>(Unknown Source)
    at processing.serial.Serial.<init>(Unknown Source)
    at sketch_211210a.draw(sketch_211210a.java:85)
    at processing.core.PApplet.handleDraw(PApplet.java:2475)
    at processing.awt.PSurfaceAWT$12.callDraw(PSurfaceAWT.java:1547)
    at processing.core.PSurfaceNone$AnimationThread.run(PSurfaceNone.java:313)
java.lang.RuntimeException: Error opening serial port /dev/tty.wchusbserial620: Port busy
java.lang.RuntimeException: Error opening serial port /dev/tty.wchusbserial620: Port busy

```

Another issue is with this part of the code: `if (device_detected)`. The `draw()` function is like the Arduino `loop()` function in that it keeps looping through the code. It is repeatedly trying to make a new serial connection to the same port, which MAY explain why the `Port busy` error message is repeated in the console error messages.

Using Processing IDE 3.5.3, there is a errors tab at the bottom of the console window. I am getting 2 errors there which don't seem to be involved with the port connection issue.

If you install the `controlP5` library in the Processing IDE, you can use this port testing sketch to see the Port ID change every time you create a new connection with it. I suspect your sketch may connect to the Arduino the first time through the `draw()` function, then it keeps trying to connect to the same port which is busy.

```
// Serial port(s) connection tester. Processing version 3.5.3.
// For a list of all the ScrollableList Controller methods available,
// use: "ControlP5.printPublicMethodsFor(ScrollableList.class);"
// to print the entire list of the 165 functions to the console.
import controlP5.*;
import java.util.*;
import processing.serial.*;

ControlP5 cp5;
Serial myPort;
Textlabel outputWindowLine1, outputWindowLine2;
String portName;

void setup(){

  size(500, 431);

  // Use a font larger than the default "6px".
  ControlFont font = new ControlFont(createFont("Verdana", 14));

  // ALL CAPS is the default font for the control. Why?
  Label.setUpperCaseDefault(false);

  // Configure a controlP5 ScrollableList.
  cp5 = new ControlP5(this);
  cp5.addScrollableList("dropdown")
    .setPosition(0, 50)
    .setSize(500, 400)
    .setBarHeight(50)
    .setItemHeight(30)
    .setFont(font)
    .addItems(GetSerialPortList())
    .setType(ScrollableList.LIST)
    .setLabel("--- Click on a port name to try and connect to it ---")
    ;

  outputWindowLine1 = cp5.addTextlabel("outputWindowLine1Label")
    .setText("The list of port names is \"scrollable\".")
    .setPosition(0, 0)
    .setColorValue(0)
    .setFont(font)
    ;

  outputWindowLine2 = cp5.addTextlabel("outputWindowLine2Label")
    .setText("Press any character on the keyboard to reload the list.")
    .setPosition(0, 25)
    .setColorValue(0)
    .setFont(font)
    ;
}

void draw(){
  background(255);
}

// User selects a drop down item. Works like a JavaScript onChange()
// event, except you can click on the same item multiple times, this
// code will execute again on each mouse "click" of the same item.
void dropdown(int n){

  // Create a serial connection and send some
  // chars to the "USB to Serial Converter".
  try{

    // Get the port name.
    portName = Serial.list()[n];

    // If you don't do this, you can't re-connect to the same port again.
    // Re-connecting to the same port gives you a new "myPort ID" and may
    // take a few seconds.
    if(myPort != null){
      myPort.clear();
      myPort.stop();
    }

    // Create a Serial Port connection.
    myPort = new Serial(this, portName, 9600);

    // User message.
    outputWindowLine1.setText("Connected to portName: " + portName);
    outputWindowLine2.setText("myPort = " + myPort);

  }
  catch(Exception e){

    // User message.
    outputWindowLine1.setText("Error connecting to portName: " + portName);
    outputWindowLine2.setText("");

    // Print detailed error information to the console.
    System.err.println(e);
    e.printStackTrace();
  }
}

// Refresh the dropdown list of serial port names.
void keyPressed(){
  cp5.get(ScrollableList.class, "dropdown").setItems(GetSerialPortList());
  outputWindowLine1.setText("Serial port list refreshed!");
  outputWindowLine2.setText("");
}

// Get a List of the serial port names.
List GetSerialPortList(){
  List serialPortList = Arrays.asList(Serial.list());
  return serialPortList;
}

```
> 3 votes

---
Tags: serial
---


# Question
Title: Question about ElapsedMillis() library and state machines
I'm making a sort of state machine with 3 states, and I'm actually doing some tests by configuring at the start of my code state=3. I've wired on each pin 2 leds, for a total of 12 leds. I'm using elapsedMillis library (https://github.com/pfeerick/elapsedMillis) to make things a bit more easy and I'm stuck at 3rd state. At the 3rd state I would like that each couple of leds will stay on for 90ms, than goes of for 1ms. elapsedMillis library allows one to do something like that:

elapsedMillis timeElapsed; //declare global if you don't want it reset every time loop runs

```
#include "elapsedMillis.h"

const int pin0 = 12;
const int pin1 = 11;
const int pin2 = 10;
const int pin3 = 9;
const int pin4 = 8;
const int pin5 = 7;

unsigned long t1 = 500;
unsigned long waiting = 1000;
unsigned long t2 = 100;
unsigned long t3 = 50;
unsigned long t4 = 1;
unsigned long t5 = 90;
unsigned long startTime = 0;

int ledArray[] = {pin0, pin1, pin2, pin3, pin4, pin5};
int j, k, a, c = 0;
int state = 3;

elapsedMillis elapsedTime;
elapsedMillis timer1;
elapsedMillis timer2;
elapsedMillis timer3;
elapsedMillis timer4;
elapsedMillis timer5;

void setup() {
  pinMode(pin0, OUTPUT);
  pinMode(pin1, OUTPUT);
  pinMode(pin2, OUTPUT);
  pinMode(pin3, OUTPUT);
  pinMode(pin4, OUTPUT);
  pinMode(pin5, OUTPUT);
  Serial.begin(9600);

}

void loop() {

  switch (state) {

    case 0:
      // led accesi in modo scalare allo stato 0
      while (k <= 5)
      {

        if (timer1 >= t1)
        {
          if (j <= 5)
          {
            digitalWrite(ledArray[j], HIGH);
            j++;
            timer1 = 0;

          }
          k++;
          elapsedTime = 0;
        }

      }
      // attendo 1s poi vado allo stato 1

      if (elapsedTime >= waiting) {
        state = 1;
        elapsedTime = 0;
      }

      break;

    case 1:

      // led spenti rapidamente in modo scalare

      while (k >= 0) {
        if (timer2 >= t2)
        {
          if (j >= 0)
          {
            digitalWrite(ledArray[j], LOW);
            j--;
            timer2 = 0;
          }
          k--;
          elapsedTime = 0;
        }
      }
      // attendo 0.1s
      if (elapsedTime >= t2) {
        state = 2;

      }
      break;

    case 2:

      // led fade per 3 volte
      if (c <= 3)
      {
        while (a <= 255)
        {
          if (timer3 >= t3) {
            analogWrite(ledArray[3], a);
            timer3 = 0;
            a += 10;

          }

        }
        while (a >= 0)
        {
          if (timer3 >= t3) {
            analogWrite(ledArray[3], a);
            timer3 = 0;
            a -= 10;
          }
        }
        c++;
      }
      else {
        state = 3;
      }

      break;

    case 3:

      if (timer4 >= t5) {
        if (j <= 5) {
          digitalWrite(ledArray[j], HIGH);
          j++;
          timer4 = 0;
          if (timer5 >= t4) {
              digitalWrite(ledArray[j], LOW);
              timer5 = 0;
            }
          }
        }
      break;
  }
}

```

---

```
case 3:

  for (int ii = 0; ii <= 5; ii++)
  {
    digitalWrite(ledArray[ii], ( (ii == j) && (timer4 < 90)));
  }

  if (timer4 > 91) {
    j += backwardScan ? -1 : 1 ;
    if (j > 5) {
      backwardScan = 1;
      j = 5;
    }
    if (j < 0) {
      backwardScan = 0;
      j = 0;
    }
    timer4 = 0;
  }
  break;

```

For the state3 I would like an effect like the "KITT" knight rider car in 80s TV show. Each couple of 2 leds should move back and forth... in shortly: first 2 leds stays on 90ms and 1ms off, then second 2 leds on 90ms and 1ms off.. etc...

It seems like the leds in the array goes on all together.

# Answer
You need to maintain more state information to have 'case 3' work like a KITT-style back and forth LED scanner. I think you can do it with three state variables, `j` for which pair of LEDs is active, `backwardsScan` to say which way to go, and `timer4` to remember where in the 91ms cycle we are with the active pair of LEDs.

Try something like this:

```
...
int backwardsScan = 0;
...

case 3: // KITT-like scanning back and forth 90us/1us
  // j remembers which LED pair is active
  // backwardsScan remembers which direction to scan
  // timer4 handles the 90ms/1ms on-off cycle.
  //
  // reset output leds appropriately for (j,timer4):
  for(int ii=0;ii<=5;ii++){
    digitalWrite(ledArray[ii],( (ii==j) && (timer4 <90)));
  }
  // update KITT state based on (j,backwardsScan,timer4)
  if(timer4 > 91){
     j += backwardsScan? -1 : 1 ;
     if (j > 5){
        backwardsScan = 1;
        j = 5;
        }
     if (j < 0) {
        backwardsScan = 0;
        j = 0;
        }
     timer4 = 0;
     }

  break;

```

The main trick with state machines is being able to fully determine the complete state from what you are keeping track of--It should be memoryless, in that the state variable(s) fully specify the state, and you don't need to remember the prior state. If you find you need to know more than one thing, you might need a vector or set of state variables. One could map the whole led-backwardsScan-timer4 state vector into a single state variable (timer4, modulo 182ms for example,) but that would be unnecessarily complicated. Recognizing all the variables required to fully specify the state is important.
> 2 votes

---
Tags: millis
---


# Question
Title: Serial connection between Processing and Arduino doesn't work
I'm trying to connect an Arduino Nano Every and Processing via serial. I'm getting no errors on either side, and the arduino serial functionality works otherwise on the arduino IDE.

I'm connecting on the right port, and the port is busy while the processing code is running (as you would expect), however, the variable inside the arduino is not updating. In fact, the whole if serial.available statement is not executing.

Arduino:

```
int var;

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

void loop() {
  if (Serial.available()) {
    var = Serial.read();
  }
  Serial.println(var);
  delay(100);
}

```

Processing:

```
import processing.serial.*;

// The serial port
Serial myPort;

void setup() {
  // List all the available serial ports:
  printArray(Serial.list());
  // open port
  myPort = new Serial(this, Serial.list()[2], 9600);
}

void draw() {
  try {
    myPort.write(1);
  }
  catch(Exception e) {
    // Print detailed error information to the console.
    System.err.println(e);
    e.printStackTrace();
  }
  delay(50);
}

```

PS. Asked moderator to close previous post on topic.

# Answer
Most Arduinos (and the Nano Every is one of them) will reset when the serial connection is reopened (You close it by closing the processing sketch and open it again with the Serial Monitor). Variables are stored in RAM, which gets wiped and reinitialized after a reset or power loss.

So this basically happens: You send the data from processing over serial to the Arduino. The Arduino puts the received value into the variable in its RAM. Then you close the processing sketch, effectively closing the serial connection. Then you open the Serial Monitor, which opens the serial connection again. This triggers the reset of the Arduino and wipes the previous variable value from the RAM. You will only ever see the initial variable value (zero) this way.

You can prevent a reset over serial if you connect a capacitor between the Reset pin and ground.

Though I would say this is probably not what you really should do. Instead just read the data from serial inside your processing sketch. After you have read it you can print it.

---

As a side note: The reset-on-serial-reconnect functionality is used for programming the Arduino over serial (through the USB cable). The new program is written into the program memory (flash) by the bootloader. The bootloader runs directly after a reset/power-on. So to upload a new program to the Arduino the Arduino IDE has to first reset the Arduino to talk to the bootloader.
> 1 votes

# Answer
If you open your Processing sketch and send the data to the Arduino without opening the serial monitor in the Arduino IDE, the data gets through. Here is your Arduino sketch which is slightly modified. Disclaimer - tested on an Uno.

There are other options for serial monitors which may work (varies by OS), as well as other options to interface between Processing and Arduino, such as Firmata

```
int var;

void setup() {
  Serial.begin(9600);
  pinMode(2, OUTPUT);
  digitalWrite(2, LOW);
}

void loop() {
  if (Serial.available()) {
    var = Serial.read();
    digitalWrite(2, HIGH);
    delay(50);
    digitalWrite(2, LOW);
  }
  Serial.println(var);
  delay(100);
}

```

**EDIT**

Arduino IDE version 1.0.6.2 with `Processing` 2.2-ish would let you open the serial monitor in the Arduino IDE and "monitor" the data. Since you can't do this anymore, what about making your `Processing` app open 2 windows. One window could be a home brewed serial monitor, and the other the sketch you are working on. Using `Processing` version 3.5.3, it is only 15 lines of code to open up 2 windows. I'm sure the actual implementation of such a system would be a good challenge.
> 1 votes

---
Tags: serial, serial-data, processing-lang
---


title: Stepper motor with microstep driver

text:
# Question
Title: Stepper motor with microstep driver
In my project I have to control a stepper motor using arduino and microstep driver, can I control the motor so that it can move 90 degrees then stop for like a second and then move again and repeat that sequence. Can I do that please help I'm stuck in the code and I couldn't figure it out.

# Answer
Of course you can! There are some excellent libraries to control steppers, e.g. Stepper or AccelStepper.

What you describe sounds like basic task that is covered in examples of these libraries. For example, this one: https://github.com/arduino-libraries/Stepper/blob/master/examples/stepper\_oneRevolution/stepper\_oneRevolution.ino. You only need to set correct pins and tweak delays and rotation angles (if your stepper has 200 steps per revolution, then 90 degrees is 50 steps).
> 1 votes

---
Tags: arduino-uno, programming, stepper
---


title: Arduino controlled 25A 12V DC relay

text:
# Question
Title: Arduino controlled 25A 12V DC relay
I have an air compressor that I often give difficult tasks, where the compressor needs to run longer than it was designed for. So it gets close to overheating, which requires periodically giving the compressor some "cool down" time, turned off.

Rather than walk into my garage every couple of minutes to turn the compressor on or off, I'd like to automate the process with a little arduino board.

The problem is the compressor is run by a 25A 12V DC line. Most relays I can find that are Arduino compatible (3.3v DC control) max out at 10A.

I'm curious if there is a smart way to do this efficiently. Two solutions that come to mind are:

1. Control 3 or 4 10A relays with the Arduino, and parallelize the current heading to the compressor across multiple relays.
2. Use one relay controlled by the Arduino, and use that relay to control a secondary big relay, that could control the 25A line.

Neither seems like a very efficient approach to the problem. I don't know for certain but I worry that perhaps with (1), one relay might be a better conductor than the others, so perhaps one might eventually see a cascade of overheating relays.

Perhaps someone here that's more familiar with circuit design could suggest a better approach.

edit: After a little digging it looks like option (2) is the standard route most often traveled.

This is an OMRON relay that is powered by a 12VDC supply (0.167A), and can switch a 28VDC 30A line. So I will double relay it, using an Adafruit featherwing to switch the 12VDC supply, which will then switch this big OMRON relay. In my pile of old AC/DC converters I found a 1A 12V supply that's sufficient to run the OMRON relay. Provided I haven't overlooked anything this is likely a decent solution.

# Answer
> 1 votes
Do not double relay it (at least not parallel aka Option 1). Relays have a tendancy to bounce or take time. This exposes you to a potential for only one relay to be connected for a time. Worse, if someone decides to use the relays as high, low instead of closed, open it will short high to low for a time.

The series relay solution is sound but not efficient. Relays are almost never the efficient approach (there are cases where infrequent switching occurs where a relay simply holding a position without power for long durations can be efficient). A relay module is essentially a mosfet and a relay. Mosfet controls the coil, and if you will have one of those, might as well go for a 12V mosfet of appropriate amperage. I used to have some arduino compatible 3D printer heat bed mosfets that went up to 25A (on paper) so I can't imagine they're impossible to obtain.

You also mention digging power supplies for your relay. If you are going so far as to need a 12V power supply, is there one providing for the compressor itself? If so, could you just control the wall outlet AC that powers the supply? Amperage would be a lot lower and AC can allow use of some rather nifty "Solid State Relay" devices (as well as relay modules, smart outlets, etc).

---
Tags: relay
---


# Question
Title: I am trying to add a countdown to my Arduino code but it does 0 days, 04:09:36 instead of starting at 7 days
The code I use probably has a math problem since an Arduino can only count a 16 bit integer. This problem is with the WeekDelay() function. The project is for an Aerogarden. It pumps water into the garden every week from information based on my collected data. It writes on the LCD information like if it is pumping, waiting (it should have the timer here and display on the LCD), and it can show when it is going to pump with a beep warning. After beeping, pumping, and waiting for a few times I run out of information and do a loop and show a warning message, blinking the LCD and pumping a set amount. More specifically WeekDelay() should be a delay for a week. It clears the LCD, Sets the cursor to 0,0 and prints "Waiting one week". It should then have a countdown of 24 hours on the screen and then just how many days it is waiting. It does that through clearing the LCD, Setting the cursor, printing days and waiting.

Because of the glitch it does not display any days even though it should show 7. It displays 04:09:36. Somebody was helping me out and said this:

*Ah, it is the integer math interacting with the size of days. 04:09:36 = 4*3600+9*60+36 = 14976 which happens to be equal to 7*24*3600 % 32768. See gammon.com.au/forum/?id=12146 and https://wiki.sei.cmu.edu/confluence/display/c/INT35-C.+Use+correct+integer+precisions for what's happening.*

This is some cut-down version of my code:

```
int beeper_pin      = 2; //Naming buzzer pin
int resetGarden_pin = 3; //Naming the warning led pin
int pump_pin        = 6; //Naming the pump pin

#include <LiquidCrystal_I2C.h> // Driver Library for the LCD Module

LiquidCrystal_I2C lcd(0x27, A4, A5);

void clearLCDLine(int line)
{
  lcd.setCursor(0, line);
  for (int n = 0; n < 20; n++) // 20 indicates symbols in line. For 2x16 LCD write - 16
  {
    lcd.print(" ");
  }
}

void beepWarning() {            //Makes beeping a subroutine

  lcd.setCursor(0, 0);
  lcd.print("WARNING");
  delay(100);
  lcd.setCursor(0, 1);
  for (int x = 0; x < 3; x++) {

    lcd.setCursor(0, 1);
    lcd.print("WATER PUMP ACTIVE");
    delay(100);
    clearLCDLine(1);
    lcd.setCursor(0, 1);
    lcd.print("WATER PUMP ACTIVE.");
    delay(100);
    clearLCDLine(1);
    lcd.setCursor(0, 1);
    lcd.print("WATER PUMP ACTIVE..");
    delay(100);
    clearLCDLine(1);
    lcd.setCursor(0, 1);
    lcd.print("WATER PUMP ACTIVE...");
    delay(100);
    clearLCDLine(1);
  }

  lcd.setCursor(0, 1);
  lcd.print("WATER PUMP ACTIVE...");

  for (int x = 0; x < 3; x++) {   //Repeats 3 times

    digitalWrite(beeper_pin, HIGH); //Turn on buzzer
    delay(100);                     //Delay of 400 milliseconds
    digitalWrite(beeper_pin, LOW);  //Turns off buzzer
    delay(100);                     //Delay of 400 milliseconds

  }
}

void SOSWarning() {            //Makes SOS a subroutine

  clearLCDLine(1);
  lcd.setCursor(0, 0);
  lcd.print("WPA Reset Aerogarden");

  for (int x = 0; x < 3; x++) {   //Repeats 3 times

    for (int d = 0; d < 3; d++) {   //Repeats 3 times
      digitalWrite(beeper_pin, HIGH); //Turn on buzzer
      delay(200);                     //Delay of 400 milliseconds
      digitalWrite(beeper_pin, LOW);  //Turns off buzzer
      delay(200);                     //Delay of 400 milliseconds
    }

    for (int a = 0; a < 3; a++) {   //Repeats 3 times
      digitalWrite(beeper_pin, HIGH); //Turn on buzzer
      delay(400);                     //Delay of 400 milliseconds
      digitalWrite(beeper_pin, LOW);  //Turns off buzzer
      delay(400);                     //Delay of 400 milliseconds
    }

    for (int d = 0; d < 3; d++) {   //Repeats 3 times
      digitalWrite(beeper_pin, HIGH); //Turn on buzzer
      delay(200);                     //Delay of 400 milliseconds
      digitalWrite(beeper_pin, LOW);  //Turns off buzzer
      delay(200);                     //Delay of 400 milliseconds
    }

    delay(500);                     //Delay of 500 milliseconds
  }
}

void weekDelay() { //Makes waiting for a week a subroutine
  clearLCDLine(1);
  clearLCDLine(0);
  lcd.setCursor(0, 0);
  lcd.print("Waiting One Week");

  unsigned long start = millis();
  unsigned long week_secs = 7 * 24 * 3600;
  unsigned long countdowntime_seconds;

  while (countdowntime_seconds = week_secs - (millis() - start)/1000){
     char buff[80];
     int countdown_day = countdowntime_seconds / 3600 / 24;
     int countdown_hour = (countdowntime_seconds / 3600) % 24;
     int countdown_minute = ((countdowntime_seconds / 60) % 60);
     int countdown_sec = countdowntime_seconds % 60;
     sprintf(buff,"%1d days, %02d:%02d:%02d",
            countdown_day,
            countdown_hour,
            countdown_minute,
            countdown_sec
            );
     Serial.print(buff);
     clearLCDLine(1);
     lcd.setCursor(2, 1);
     lcd.print(buff);
     delay(1000);
     }
}

void pumpOn() {               //Makes turning on the pump a subroutine
  clearLCDLine(1);
  lcd.setCursor(0, 1);
  lcd.print("PUMPING");
  delay(100);
  digitalWrite(pump_pin, HIGH); //Turning on the pump
}

void pumpOff() {              //Makes turning off the pump a subroutine
  digitalWrite(pump_pin, LOW);  //Turning off the pump
  clearLCDLine(1);
  lcd.setCursor(0, 1);
  lcd.print("WATER PUMP OFF");
  delay(1000);
}

void setup() {
  //run once:
  lcd.backlight();
  lcd.init();

  lcd.setCursor(4, 0);//////////////////////////////////////////////////////
  lcd.print("HH:MM:SS"); //////////////////////////////////////////////////

  lcd.clear(); // Clear the screen
  lcd.setCursor(0, 0);
  lcd.print("Aero_Pump V3");
  delay(1000);
  lcd.setCursor(0, 1);
  lcd.print("By Alex");
  delay(1000);
  pinMode (beeper_pin,      OUTPUT); //Setting outputs
  pinMode (resetGarden_pin, OUTPUT); //Setting outputs
  pinMode (pump_pin,       OUTPUT); //Setting outputs
  lcd.clear(); // Clear the screen

  digitalWrite(resetGarden_pin, LOW); //Turning off the reset garden light

  beepWarning(); //Beeps a warning
  pumpOn();      //Turns on the pump
  delay(3000);  //Adds a delay of 24000 milliseconds
  pumpOff();     //Turns off the pump
  weekDelay();   //Waits a week

  beepWarning(); //Beeps a warning
  pumpOn();      //Turns on the pump
  delay(12000);  //Adds a delay of 24000 milliseconds
  pumpOff();     //Turns off the pump
  weekDelay();   //Waits a week
}

void loop() {

  SOSWarning(); //Beeps an SOS warning
  pumpOn();      //Turns on the pump
  delay(48000);  //Adds a delay of 48000 milliseconds
  pumpOff();     //Turns off the pump

  for (int x = 0; x < 3024000; x++) {
    lcd.backlight(); // turn on backlight.
    delay(100);
    lcd.noBacklight(); // turn off backlight
    delay(100);
  }
  lcd.backlight(); // turn on backlight.
}

```

This is the function that needs to be fixed:

```
void weekDelay() { //Makes waiting for a week a subroutine
  clearLCDLine(1);
  clearLCDLine(0);
  lcd.setCursor(0, 0);
  lcd.print("Waiting One Week");

  unsigned long start = millis();
  unsigned long week_secs = 7 * 24 * 3600;
  unsigned long countdowntime_seconds;

  while (countdowntime_seconds = week_secs - (millis() - start)/1000){
     char buff[80];
     int countdown_day = countdowntime_seconds / 3600 / 24;
     int countdown_hour = (countdowntime_seconds / 3600) % 24;
     int countdown_minute = ((countdowntime_seconds / 60) % 60);
     int countdown_sec = countdowntime_seconds % 60;
     sprintf(buff,"%1d days, %02d:%02d:%02d",
            countdown_day,
            countdown_hour,
            countdown_minute,
            countdown_sec
            );
     Serial.print(buff);
     clearLCDLine(1);
     lcd.setCursor(2, 1);
     lcd.print(buff);
     delay(1000);
     }
}

```

# Answer
As the comment already tells, you are trying to calculate a constant with `int` literals that overflows:

`unsigned long week_secs = 7 * 24 * 3600;`

This is 604800 (0x93A80), but since `int`s are just signed 16 bits numbers (with your compiler system), only the lower 16 bits are taken into account. Fortunately these lower 16 bits are positive in two's complement, and so you get 14976 (hex 0x3A80).

The correct statement uses at least one `unsigned long` value, and the integer promotion rules make sure that all values are converted to that type, too.

`unsigned long week_secs = 7UL * 24 * 3600;`
> 1 votes

---
Tags: programming, arduino-nano, lcd, timers, code-review
---


# Question
Title: Random access to SD card using SD.h or another library (ESP32)
I'm trying to use a SD card with my ESP32 in order to save some variables in a txt file. Each variable uses 1 byte, so they can be represented by an 8 bit extended ASCII character.

The issue is it seems that the SD.h library has only 3 open modes (Read only, `FILE_WRITE`, `FILE_APPEND`), and I cannot figure out how to use random access for writing a specific byte of the file.

Imagine the situation: I have a file called `myFile.txt` which initially has a size of 5 bytes, and its content is: `abcde`

The code I'm using is the following:

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

#define SD_CS_PIN 5

File myFile;

void setup() {
  // Open serial communications and wait for port to open:
  Serial.begin(115200);
  while (!Serial) {
    ; // wait for serial port to connect. Needed for native USB port only
  }

  Serial.println("Initializing SD card...");

  if (!SD.begin(SD_CS_PIN)) {
    Serial.println("initialization failed!");
    return;
  }
  Serial.println("initialization done.");

  myFile = SD.open("/myFile.txt", FILE_WRITE);
  myFile.seek(3);
  myFile.write('a');
  myFile.close();

}

void loop() {}

```

But after running the code, the file has an unexpected behaviour, its size changes from 5 bytes to 4 bytes, and its content is: `abca` instead of the expected `abcae`

I know it happens because when writing into the file I'm using the open mode `FILE_WRITE` which uses the `FILE_APPEND` mode internally, so when doing `myFile.seek(3);`, I'm truncating the file to 4 bytes since the `FILE_APPEND` mode needs to point to the end of the file.

So, my question is, how can I open a file in random access mode with SD.h, or another library?

Thanks in advance!

# Answer
> 3 votes
**Solved!**

The solution was to migrate from the `SD` library to `mySD`, which seems to be a `SdFat` wrapper for ESP32.

You can see in the file `mySD.h` that the `FILE_WRITE` mode is defined as:

```
#define FILE_WRITE (F_READ | F_WRITE | F_CREAT)

```

Which means that it allows random access to the file for writing (`F_WRITE` instead of `FILE_APPEND`).

**PS:** I want to remark @Juraj comment since the forum is mainly for Arduino board questions

> the SD library in ESP32 boards support package is different than the standard Arduino SD library

---
Tags: esp32, sd, sd.h
---


# Question
Title: ESP32: spi_master: check_trans_valid(801) when using SPI
I use the following code to communicate with a display:

```
void Display_HandleDC(spi_transaction_t* p_Transaction)
{
    gpio_set_level((gpio_num_t)LCD_DC, (uint32_t)p_Transaction->user);
}

static void Display_SendCommand(const uint8_t Command)
{
    spi_transaction_t t;

    memset(&t, 0, sizeof(t));

    t.length = 8;
    t.tx_buffer = &Command;
    t.user=(void*)0;

    assert(spi_device_polling_transmit(_SPI, &t) == ESP_OK);
}

static void Display_SendData(const uint8_t* p_Data, uint32_t Length)
{
    spi_transaction_t t;

    if(Length == 0)
    {
        return;
    }

    memset(&t, 0, sizeof(t));

    t.length = Length * 8;
    t.tx_buffer = p_Data;
    t.user=(void*)1;

    assert(spi_device_polling_transmit(_SPI, &t) == ESP_OK);
}

static uint32_t Display_ReadID(void)
{
    spi_transaction_t t;

    Display_SendCommand(0x04);

    memset(&t, 0, sizeof(t));
    t.length = 4 * 8;
    t.flags = SPI_TRANS_USE_RXDATA;
    t.user = (void*)1;

    assert(spi_device_polling_transmit(_SPI, &t) == ESP_OK);

    return *(uint32_t*)t.rx_data;
}

static void Display_Write(int ypos, uint16_t *linedata)
{
    static spi_transaction_t trans[6];

    for(uint8_t x=0; x<6; x++)
    {
        memset(&trans[x], 0, sizeof(spi_transaction_t));
        if ((x&1)==0) {
            //Even transfers are commands
            trans[x].length=8;
            trans[x].user=(void*)0;
        } else {
            //Odd transfers are data
            trans[x].length=8*4;
            trans[x].user=(void*)1;
        }

        trans[x].flags = SPI_TRANS_USE_TXDATA;
    }

    trans[0].tx_data[0] = 0x2A;
    trans[1].tx_data[0] = 0;
    trans[1].tx_data[1] = 0;
    trans[1].tx_data[2] = 320 >> 8;
    trans[1].tx_data[3] = 320 & 0xFF;

    trans[2].tx_data[0] = 0x2B;
    trans[3].tx_data[0] = ypos >> 8;
    trans[3].tx_data[1] = ypos & 0xFF;
    trans[3].tx_data[2] = (ypos + 1) >> 8;
    trans[3].tx_data[3] = (ypos + 1) & 0xFF;

    // Write the data to memory
    trans[4].tx_data[0] = 0x2C;
    trans[5].tx_buffer = linedata;
    trans[5].length = 320 * sizeof(uint16_t) * 8;
    trans[5].flags = 0x00;

    for(uint8_t x = 0; x<6; x++)
    {
        assert(spi_device_queue_trans(_SPI, &trans[x], portMAX_DELAY) == ESP_OK);
    }
}

static void Display_Busy(void)
{
    spi_transaction_t* rtrans;
    for(uint8_t x=0; x<6; x++)
    {
        assert(spi_device_get_trans_result(_SPI, &rtrans, portMAX_DELAY) == ESP_OK);
    }
}

esp_err_t Display_Init(void)
{
    static uint16_t* Line;

    gpio_set_direction((gpio_num_t)LCD_DC, GPIO_MODE_OUTPUT);
    gpio_set_direction((gpio_num_t)LDC_RESET, GPIO_MODE_OUTPUT);
    gpio_set_direction((gpio_num_t)LCD_BACKLIGHT, GPIO_MODE_OUTPUT);

    if((spi_bus_initialize(HSPI_HOST, &_BusCfg, 0) != ESP_OK) || (spi_bus_add_device(HSPI_HOST, &_DevDcfg, &_SPI) != ESP_OK))
    {
        return ESP_FAIL;
    }

    Display_Reset();
    ESP_LOGI(TAG, "ID: %08X", Display_ReadID());

    uint32_t Commands = sizeof(_Init_Cmd_List) / sizeof(_Init_Cmd_List[0]);
    ESP_LOGI(TAG, "Loading initialization commands: %u", Commands);

    for(uint32_t i = 0x00; i < Commands; i++)
    {
        ESP_LOGI(TAG, "     Command %u / %u", i + 1, Commands);
        Display_SendCommand(_Init_Cmd_List[i].Command);
        Display_SendData(_Init_Cmd_List[i].Data, _Init_Cmd_List[i].Length & 0x1F);
        if(_Init_Cmd_List[i].Length & 0x80)
        {
            vTaskDelay(100 / portTICK_RATE_MS);
        }
    }

    Line = (uint16_t*)heap_caps_malloc(320 * sizeof(uint16_t), MALLOC_CAP_DMA);
    if(Line == NULL)
    {
        return ESP_FAIL;
    }

    for(uint32_t i = 0x00; i < 320; i++)
    {
        Line[i] = 0xF8;
    }

    Display_Write(0, Line);
    Display_Busy();
    free(Line);

    return ESP_OK;
}

```

And this code results in the following error message:

```
E (1833) spi_master: check_trans_valid(801): txdata transfer > host maximum
assertion "spi_device_queue_trans(_SPI, &trans[x], portMAX_DELAY) == ESP_OK" failed: file "src/Peripherals/Display/display.cpp", line 225, function: void Display_Write(int, uint16_t*)
abort() was called at PC 0x400e47a4 on core 1

ELF file SHA256: bc86d952445723b2

Backtrace: 0x4008e8c0:0x3ffb4b30 0x4008ecb9:0x3ffb4b50 0x400e47a4:0x3ffb4b70 0x400d170d:0x3ffb4ba0 0x400d1873:0x3ffb4bc0 0x400d13ea:0x3ffb4bf0 0x400d194b:0x3ffb4c20 0x40088601:0x3ffb4c40
  #0  0x4008e8c0:0x3ffb4b30 in invoke_abort at .platformio\packages\framework-espidf@3.40001.200521\components\esp32/panic.c:155
  #1  0x4008ecb9:0x3ffb4b50 in abort at .platformio\packages\framework-espidf@3.40001.200521\components\esp32/panic.c:172
  #2  0x400e47a4:0x3ffb4b70 in __assert_func at /builds/idf/crosstool-NG/.build/HOST-i686-w64-mingw32/xtensa-esp32-elf/src/newlib/newlib/libc/stdlib/assert.c:62 (discriminator 8)
  #3  0x400d170d:0x3ffb4ba0 in Display_Write(int, unsigned short*) at src/Peripherals/Display/display.cpp:225 (discriminator 1)
  #4  0x400d1873:0x3ffb4bc0 in Display_Init() at src/Peripherals/Display/display.cpp:288
  #5  0x400d13ea:0x3ffb4bf0 in setup() at src/Application/application.cpp:21
  #6  0x400d194b:0x3ffb4c20 in applicationTask(void*) at src/main.cpp:41
  #7  0x40088601:0x3ffb4c40 in vPortTaskWrapper at .platformio\packages\framework-espidf@3.40001.200521\components\freertos/port.c:143

```

But the error doesn´t occur when I change the DMA channel from `0` to `1`:

```
if((spi_bus_initialize(HSPI_HOST, &_BusCfg, 1) != ESP_OK) || (spi_bus_add_device(HSPI_HOST, &_DevDcfg, &_SPI) != ESP_OK))
{
    return ESP_FAIL;
}

```

What´s the difference between both channels and why is only channel `1` working?

# Answer
> 2 votes
Your code initializes the SPI bus by calling the `spi_bus_initialize(HSPI_HOST, &_BusCfg, 0)` function. The last argument of this function (`int dma_chan`) defines the DMA channel to use, which can be 0, 1 or 2.

Selecting DMA channel "0" will actually not select a DMA channel at all (which is explained in the Espressif documentation):

* **dma\_chan**: Either channel 1 or 2, *or 0 in the case when no DMA is required*. Selecting a DMA channel for a SPI bus allows transfers on the bus to have sizes only limited by the amount of internal memory. *Selecting no DMA channel (by passing the value 0) limits the amount of bytes transfered to a maximum of 32.*

The reason you get an error when your ESP32 tries to do an SPI transfer when no DMA channel is selected (option 0), is that the transfer apparently is larger than 32 bytes.

The error produced is "*E (1833) spi\_master: check\_trans\_valid(801): txdata transfer \> host maximum*", which reflects that.

The reason DMA channel 1 works correctly, is because that is an actual DMA channel and it has no limit on the amount of bytes transferred (only limited by the amount of internal memory).

---
Tags: esp32, spi
---


# Question
Title: When using the IRremote library- why does it say 64 bits when after converting the hex to binary it comes out to be less?
I get this code output on my Serial when the IR receiver gets a signal:

```
Protocol  : GREE
Code      : 0x01C02350000000E0 (64 Bits)
Mesg Desc.: Model: 1 (YAW1F), Power: Off, Mode: 1 (Cool), Temp: 16C, Fan: 0 (Auto), Turbo: Off, Econo: Off, IFeel: Off, WiFi: Off, XFan: Off, Light: On, Sleep: Off, Swing(V) Mode: Manual, Swing(V): 0 (Last), Swing(H): 0 (Off), Timer: 23:00, Display Temp: 0 (Off)
uint16_t rawData[279] = {...

```

When I convert `0x01C02350000000E0` to binary, however, it usually comes out to less than 64 bits. I'm assuming it has to do with the parameters of my IR receiver and not normal.

# Answer
You are confusing the data size and the value size.

Yes, your value can be represented using fewer than 64 bits, but the data size that is used to contain that value is 64 bits in size.

It's like saying that "4" is stored in a 6 digit storage space. It only needs 1 storage slot, but the allocated space is 6 digits. So what is actually stored would be "000004".

As humans we tend to throw away the leading zeroes because they are meaningless. That's because we are able to use flexible storage sizes in our brains. The computer, though, works on fixed sizes - 8 bit, 16 bit, 32 bit, 64 bit, etc.

You can't store that value in a 32 bit variable, but you can in a 64 bit one. It may be wasteful for that specific value, but it's the smallest size that is available that is big enough.
> 0 votes

---
Tags: ir, serial-data, hex
---


title: Digital Pins Question

text:
# Question
Title: Digital Pins Question
I am new to the world of Arduino and need a little bit of help. I have an Arduino Uno and I am trying to supply 5V to an actuator using the digital pins. It is my understanding that the board I have is capable of doing that. But I can't seem to get 5V from my digital pins.

I would really prefer to not have to use the 5V power pin because I need to supply multiple sources with 5V in an alternating pattern, which I know I can do with the digital pins.

Could I use the analog pins to help with this? Could I supply more power using a battery? Etc.

Thank you in advance.

# Answer
> 7 votes
The digital pins of the Arduino are rated to reliably deliver up to 20 mA. Their *absolute maximum rating* is 40 mA. Anything above that risks destroying the microcontroller.

If your device is supposed to pull from 0.24 to 0.38 A, that is too much for your Arduino pins. With such a high current, you are seeing a significant voltage drop caused by the internal resistance of the output transistors. Or it could be that you already fried those transistors.

# Answer
> 5 votes
The most common solution is to use the digital output to turn on a MOSFET that supplies separate power to a high-current device that needs more current than the 20 mA that an ATmega328 microcontroller can safely supply.

The MOSFET is chosen based on the desired current and with the need for a logic-level input.

A typical circuit:

simulate this circuit – Schematic created using CircuitLab

D1 is needed for an inductive load like a motor. It protects other components.

You might get away without using the resistors (connecting D1 directly to the MOSFET's gate) but the 10 K "pull-down" resistor R1 ensures that the load is off when the Arduino is powering up. Resistor R2 is probably mainly useful for noisy or high-frequency applications..

---
Tags: power, digital
---


# Question
Title: How to send non char variables over serial
I'm trying to build a GUI that sends the data from processing to arduino via serial. With the help of a couple of guys on here, I have come up with a basic framework that sends a variable ID, variable value and termination character (\n). So far so good!

However, the \[arduino reference\]\[1\] advises to only use `char` for storing characters. How would I send a `byte` or `int` over serial, while still being able to use a termination character to ensure everything is working as expected?

**edit:** Using the arduino code from Edgar's answer below and the following processing code, I get the "could not parse value" error.

```
import processing.serial.*;

SerialConnection serialConnection;

boolean data_processed = false;
char[] var_array = new char[31];
char var_id;
char var_val;
char space = ' ';
char termchar = '\n';

void setup() {
  serialConnection = new SerialConnection(this, 9600);
}

void draw() {
  serialConnection.startSerialCommunication();

  if (serialConnection.isReady) {
    var_id = 'a';
    var_val = 127;
    serialConnection.serialPort.write(var_id);
    serialConnection.serialPort.write(space);
    serialConnection.serialPort.write(var_val);
    serialConnection.serialPort.write(termchar);

    delay(50);
    while (serialConnection.serialPort.available() > 0) {
      for (int i = 0; i < 30; i++) {
        char inchar = serialConnection.serialPort.readChar();
        var_array[i] = inchar;
        print(var_array[i]);
      }
    }
  }
}

```

# Answer
If you want to send numeric values to your Arduino, the simplest option is to send them formatted as ASCII text. Thus you end up simply sending characters.

Let's assume for example a simple text-based protocol of the form

```
foo 42
bar 5678
baz -12

```

Each message is made of a variable name followed by its numeric value. The name and the value a separated by a space. Each message is terminated by a line feed (`'\n'`).

In order to parse a message, you first have to split it at the space character. The `strsep()` function comes handy for this. Then, you have to parse the second part of the message (the value) as an integer. I would use `strtol()` for this job. Putting all together:

```
void process(char *message) {
    char *name = strsep(&message, " ");  // split at the space
    if (!message) {
        Serial.println("Error: no value given");
        return;
    }
    char *endp;  // end of the numeric value
    long value = strtol(message, &endp, 0);
    if (endp == message) {
        Serial.println("Error: could not parse value");
        return;
    }
    /* Successfully parsed. */
    Serial.print(name);
    Serial.print(" received value ");
    Serial.println(value);
}

```

Note there are some sanity checks in order to make sure the message does match the expected format. Obviously, you have to replace the last three lines by something more meaningful to your application.

Example sketch using this:

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

void loop() {
    static char buffer[40];
    static size_t buffer_pos = 0;
    while (Serial.available()) {
        char c = Serial.read();
        if (c == '\n') {  // end of message
            buffer[buffer_pos] = '\0';  // terminate the string
            process(buffer);
            buffer_pos = 0;  // reset for next message
        } else if (buffer_pos < sizeof buffer - 1) {
            buffer[buffer_pos++] = c;  // buffer the character
        }
    }
}

```
> 2 votes

---
Tags: serial
---


# Question
Title: Is an ESP32 HTTP web server limited to a certain number of Base64 images?
This sketch only displays about nine images (when there are more). Does this mean the ESP32 is limited amount of Base64 images able to be displayed?

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

const char* ssid = "ESP32";
const char* password = "12345678";

IPAddress local_ip(192,168,1,1);
IPAddress gateway(192,168,1,1);
IPAddress subnet(255,255,255,0);

WebServer server(80);

// Used for determining the selected pattern and HTML to display:
int pattern = 0;
int selectedPattern = 0;

String circleString = "<img src=\"data:image/png;base64,[encoded data, 6912 characters]\" alt=\"NAME\" style=\"width:100%\">\n";

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

  WiFi.softAP(ssid, password);
  WiFi.softAPConfig(local_ip, gateway, subnet);
  delay(100);

  server.on("/", handle_OnConnect);
  server.onNotFound(handle_NotFound);

  server.begin();
  Serial.println("HTTP server started");
}
void loop()
{
  server.handleClient();

}

void handle_OnConnect() {

  server.send(200, "text/html", SendHTML(selectedPattern));
}

void handle_NotFound(){
  server.send(404, "text/plain", "Not found");
}

String SendHTML(int pattern)
{
    String ptr = "<!DOCTYPE html> <html>\n";
    // Instance of class String (not a pointer)

    ptr += "<head><meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0, user-scalable=no\">\n";
    // <meta> viewport element makes the web page responsive in any web browser
    // https://www.w3schools.com/css/css_rwd_viewport.asp

    ptr += "<style type=\"text/css\">\n";
    ptr +="</style>\n";

    ptr +="</head>\n";
    ptr +="<body>\n";

      /*  */
      ptr += "<div class=\"column\">\n"; // 1
        ptr += circleString;
      ptr += "</div>\n";

      ptr +="<a class=\"button\" href=\"/circle#1\">1</a>\n";

      ptr += "<div class=\"column\">\n"; // 2
        ptr += circleString;
      ptr += "</div>\n";

      ptr +="<a class=\"button\" href=\"/circle#1\">2</a>\n";

      ptr += "<div class=\"column\">\n"; // 3
        ptr += circleString;
      ptr += "</div>\n";

      ptr +="<a class=\"button\" href=\"/circle#1\">3</a>\n";

      ptr += "<div class=\"column\">\n"; // 4
        ptr += circleString;
      ptr += "</div>\n";

      ptr +="<a class=\"button\" href=\"/circle#1\">4</a>\n";

      ptr += "<div class=\"column\">\n"; // 5
        ptr += circleString;
      ptr += "</div>\n";

      ptr +="<a class=\"button\" href=\"/circle#1\">5</a>\n";

      ptr += "<div class=\"column\">\n"; // 6
        ptr += circleString;
      ptr += "</div>\n";

      ptr +="<a class=\"button\" href=\"/circle#1\">6</a>\n";

      ptr += "<div class=\"column\">\n"; // 7
        ptr += circleString;
      ptr += "</div>\n";

      ptr +="<a class=\"button\" href=\"/circle#1\">7</a>\n";

      ptr += "<div class=\"column\">\n"; // 8
        ptr += circleString;
      ptr += "</div>\n";

      ptr +="<a class=\"button\" href=\"/circle#1\">8</a>\n";

      ptr += "<div class=\"column\">\n"; // 9
        ptr += circleString;
      ptr += "</div>\n";

      ptr +="<a class=\"button\" href=\"/circle#1\">9</a>\n";

      ptr += "<div class=\"column\">\n"; // 10
        ptr += circleString;
      ptr += "</div>\n";

      ptr += "<div class=\"column\">\n"; // 11
        ptr += circleString;
      ptr += "</div>\n";

      ptr += "<div class=\"column\">\n"; // 12
        ptr += circleString;
      ptr += "</div>\n";

      ptr += "<div class=\"column\">\n"; // 13
        ptr += circleString;
      ptr += "</div>\n";

    ptr +="</body>\n";
    ptr +="</html>\n";

    return ptr;

}

```

> Sketch uses 726230 bytes (55%) of program storage space. Maximum is 1310720 bytes. Global variables use 39384 bytes (12%) of dynamic memory, leaving 288296 bytes for local variables. Maximum is 327680 bytes.

# Answer
> 1 votes
You build up the HTML website by concatting strings together by hand in the code. I know this is done in many code throughout the internet, but this is only really practical, if you need to change the website content with every request. Normally it is better to use SPIFFS (or now LittleFS) to store the files and let a fitting webserver library serve them as static files. Additionally you are making Swiss cheese out of your heap memory when you concat `String` variables this often and you might run out of RAM.

I'm not used to LittleFS, so I will write this answer using SPIFFS. But I'm sure you can use LittleFS in a very similar way. I will leave it to you to determine how it fits in with code for SPIFFS.

Have a look at the ESPAsyncWebServer library and its simple server example. I've used this library for my projects. Try the examples, read the documentation and get an idea how this library is working.

Then have a look at the documentation where it says "Serving static files". I think you want to serve your static files from a directory. That way the library will look for requested files in that complete directory inside of the SPIFFS. Inside that directory you will have your HTML website (named as `index.html`) and all the images as binary data in a format, that a webbrowser can read (like jpg, png, ...). In your HTML website you reference the images with their path. Since in this scenario they all lie in the root directory the path is only the filename (+ the files extension).

When the webbrowser requests the `index.html` from the ESP, the library will serve it from SPIFFS. The webbrowser interprets the site and sees the references to the images. It than tries to load these images, meaning it sends requests to the ESP with the path of the images. The library will search for these files in SPIFFS, will find them and serve them to the webbrowser, who will then display them on the website.

Something like this:

```
#include "ESPAsyncWebServer.h"
#include "SPIFFS.h"

AsyncWebServer server(80);

void setup(){
  Serial.begin(115200);
  while(!SPIFFS.begin()){
    Serial.println("Could not mount SPIFFS");
    delay(500);
  }
  server.serveStatic("/", SPIFFS, "/").setDefaultFile("index.html");
  server.begin();
}

void loop(){
}

```

Note:

* I've left out all Wifi related stuff. You need to add that yourself.
* I've not tested this code, just put it together from one of my working bigger programs.
* You still need to upload the actual files to the ESP SPIFFS. There are many tutorials on how to do that. Just place your files in the root directory of SPIFFS.

---
Tags: esp32, memory
---


title: Add library to CLion project

text:
# Question
Title: Add library to CLion project
I have a new project created with PlatformIO in CLion. I've copied the *Servo-1.1.8* library into the `include` directory.

```
#include <Arduino.h>
#include "Servo-1.1.8/src/Servo.h"

Servo servo;

void setup() {
}

void loop() {
}

```

I'm getting a compilation error though:

```
====================[ Build | Production | uno ]================================
C:\Users\USER_NAME\AppData\Local\JetBrains\Toolbox\apps\CLion\ch-0\213.5744.254\bin\cmake\win\bin\cmake.exe --build C:\Users\USER_NAME\Documents\Arduino\MultiServoCallibration\cmake-build-uno --target Production
[1/1] cmd.exe /C "cd /D C:\Users\USER_NAME\Documents\Arduino\MultiServoCallibration && platformio -c clion run -euno"
FAILED: CMakeFiles/Production C:/Users/USER_NAME/Documents/Arduino/MultiServoCallibration/cmake-build-uno/CMakeFiles/Production
cmd.exe /C "cd /D C:\Users\USER_NAME\Documents\Arduino\MultiServoCallibration && platformio -c clion run -euno"
Processing uno (platform: atmelavr; board: uno; framework: arduino)
--------------------------------------------------------------------------------
Verbose mode can be enabled via `-v, --verbose` option
CONFIGURATION: https://docs.platformio.org/page/boards/atmelavr/uno.html
PLATFORM: Atmel AVR (3.4.0) > Arduino Uno
HARDWARE: ATMEGA328P 16MHz, 2KB RAM, 31.50KB Flash
DEBUG: Current (avr-stub) On-board (avr-stub, simavr)
PACKAGES:
 - framework-arduino-avr 5.1.0
 - toolchain-atmelavr 1.70300.191015 (7.3.0)
LDF: Library Dependency Finder -> https://bit.ly/configure-pio-ldf
LDF Modes: Finder ~ chain, Compatibility ~ soft
Found 5 compatible libraries
Scanning dependencies...
No dependencies
Building in release mode
Compiling .pio\build\uno\src\main.cpp.o
Linking .pio\build\uno\firmware.elf
C:\Users\USER_NAME\AppData\Local\Temp\ccmN7v6f.ltrans0.ltrans.o: In function `_GLOBAL__sub_I_servo':
<artificial>:(.text.startup+0x98): undefined reference to `Servo::Servo()'
collect2.exe: error: ld returned 1 exit status
*** [.pio\build\uno\firmware.elf] Error 1
========================== [FAILED] Took 1.18 seconds ==========================
ninja: build stopped: subcommand failed.

```

I've never used CMake before, so it might well be something super simple like adding a line to some config to include that library.

# Answer
For what it's worth, I asked a similar question on StackOverflow, on the chance that the slightly different crowd might include someone who uses CLion + PlatformIO for non-Arduino embedded work and has a more authoritative opinion on the topic.

I have no idea whether it's actually safe or a good idea, but for what it's worth, I was able to add an Arduino library to **my** project by doing the following:

1. Install PlatformIO with bundled VS Code, install CLion, then configure CLion to use PlatformIO.
2. Using CLion, create a new PlatformIO Arduino sketch. Let CLion spin its wheels, do some things that might or might not have ultimately made a difference, and make sure it's in a state where it can build and deploy successfully using CLion. I personally just called Serial.start(9600) and Serial.println("something") to output to serial, then verified it actually worked.
3. Exit CLion, and launch VS Code. Add the folder containing the sketch created in step 2 to its workspace.
4. Use VS Code to add the library. Wait for it to finish downloading, and exit VS Code.
5. Relaunch CLion, and try to use the new library.

Be warned, I have absolutely *no idea* yet whether or not this is actually kosher. I'm under the impression that when you're using PlatformIO with CLion, 100% of everything is actually managed by PlatformIO, and all CLion itself does is stub through the call to launch CMake. Assuming VS Code is the same way, this should theoretically be OK... but until someone intimately familiar with PlatformIO and the way it integrates with both CLion and VS Code reassures me that it is, I'm a little bit nervous about it.

That said... if it actually *is* safe to do, it's probably the best way to add an Arduino library to a CLion-PlatformIO project since (AFAIK) CLion itself has absolutely no comparable functionality (via the PlatformIO plugin or otherwise), and I've encountered a few libraries for SSD1306 OLED use that are a major *pain* to copy into a project by hand from their Github repo (because the OLED library has dependencies on somebody else's graphics library, which itself has dependencies on somebody else's math library and menu library, the menu library has dependencies on one or two more libraries... well, you get the idea. Pain. The exact reason things like Gradle and Maven exist for Android & Java, and CMake theoretically now exists for C(++), even though it still seems to be pretty useless in Arduino-land. ;-)
> 1 votes

---
Tags: library, compilation-errors, ide, platformio
---


# Question
Title: Why do we add delay when using ultrasonic sensors?
I'm a beginner in Arduino and recently i got myself an Ultrasonic sensor (HC-SR04).

I looked up tutorials on how to measure distance with the sensor and the code I'm using is:

```
const int trigPin = 8;
const int echoPin = 7;

long duration;
int distance;

void setup() {
  // put your setup code here, to run once:
  pinMode(trigPin, OUTPUT);
  pinMode(echoPin, INPUT);
  Serial.begin(9600);
}

void loop() {
  // put your main code here, to run repeatedly:
  digitalWrite(trigPin, LOW);
  delayMicroseconds(2); //why do we delay 2 microseconds

  digitalWrite(trigPin, HIGH);
  delayMicroseconds(10); //why do we delay 10 microseconds
  digitalWrite(trigPin, LOW);

  duration = pulseIn(echoPin, HIGH);
  distance = duration*0.034/2;
  Serial.print("Distance: ");
  Serial.println(distance);
}

```

I would like to know why do we add delays in the loop function? Appreciate if anyone could explain it.

# Answer
We need to provide the HC-SR04 with a fitting trigger signal. When you read the datasheet of the HC-SR04 you will see that it needs a 10us trigger pulse.

The first delay of 2us is to make sure we are at an established LOW level on the trigger pin, since the pin might have been HIGH before that. We are delaying here to make sure, that the HC-SR04 actually registered the level as LOW, even if it was HIGH before. If we would change from HIGH to LOW and back to HIGH as fast as we can, then the HC-SR04 might not have enough time to actually see the pin going low. Its mostly a measure to ensure the code working correctly here.

The second delay is for the actual trigger pulse. The datasheet specifies it as 10us length, so that is what we delay here. After that we go back to LOW to end the trigger pulse and wait for the echo pulse to come.

You might have read that it is bad to use delays in your code, since they are blocking. That is correct in principle, but normally really short delays in the microsecond range don't really matter for the program flow. Just be away to keep the total delay time in your code low enough to not miss any important events (like button presses).
> 10 votes

---
Tags: arduino-uno, sensors
---


# Question
Title: How to distinguish identical Arduinos from Linux?
I have two identical (but with different software) Arduinos connected to Linux box. Their serals are identical

```
# udevadm info -a -n /dev/ttyUSB1 | grep '{serial}'
    ATTRS{serial}=="0000:00:1d.0"

# udevadm info -a -n /dev/ttyUSB0 | grep '{serial}'
    ATTRS{serial}=="0000:00:1d.0"

```

Can I make these Arduinos to differ somehow programmatically?

# Answer
> 3 votes
You can't change the USB information programmatically. The fact that you're referencing `/dev/ttyUSB*` means you have hardware USB interface chips (CH340, PL2302, FT232, etc) which you can't change from your sketch (some can be adjusted using tools provided by the chip manufacturer though, so you may be able to tweak it using that).

Instead your only option is to have some kind of "fingerprint" that software on your computer can request from your firmware. If you stick to a common serial protocol for all your firmwares you can implement a standard "Firmware Version" command which will respond with what code and version you have installed.

It's up to you to decide how best to implement such a system, of course.

---
Tags: serial, linux
---


# Question
Title: arduino 28BYJ-48 stepper only whining, not rotating
***Edit, this question has been answered in the comments by chrisl, and also after retesting the code with delay() which showed I forgot to update my lastupdate variable(eerst), I have answered it in the comments and chrisl possibly also will post their findings in a answer*** *TLDR- 28BYJ-48 unipolar 5v not working only whining. run using transistors and code in the bottom of the post. transistors connected to 5V and resistors ranging from 100ohm to 1000ohm tried from Arduino to the transistors Trigger/Gate. - END TLDR*

More Detailed I have some 5v and 12v 28BYJ-48 unipolar stepper motors,(I only connect one to the Arduino at a time) the common(tested with resistance meter) is connected to +, and I the other pins are connected to one BC336 transistor per pin so 4 in total. these transistors should handle 0.8A a piece and I measured the maximum amperage used by the coils to be 0.2+-0.02A for the 5v version at 5v, and 0.045 +- 0.001A for the 12v version at 5v. it makes sense if the 12v version doesn't work at 5v, I just wanted to test it to have an ultra-low-power stepper motor. however the 5v version should work, My setup allows a higher voltage drop in the coils in the motor and can handle a higher amperage than a normal driver however this is limited by the motors resistance ofcource. I drive it according to the steps in the datasheet with the standard method. and simplified my code to leave out all extra things and even hardcoding the values but still it only whiles and doesn't run the motor. I use the Arduino 5v to run the stepper motor but according to the datasheet and my measurements, you could drive more than one stepper motor on the 5v pin, even when running from USB power. I also set it really slow so that it should work(based on datasheet). I want to get this working like this because I am working on a custom budget stepper driver for Arduino which allows much simpler control, and which is much cheaper than the current drivers as well as that it by default can run higher voltage stepper motors as well, and one very specific functionality which almost everyone who has ever used one stepper motor or more has hoped that their stepper motor driver had.

I used pin 8 9 10 and 11 **Broken Code:**

```
unsigned long eerst=0;
unsigned long nu=0;
int state=0;
byte vals[8]={0b00000001,0b00000011,0b00000010,0b00000110,0b00000100,0b00001100,0b00001000,0b00001001};//made hardcoderd aray to make sure fault wasn't in the cyclic bitshifting

void setup() {
  //0b76543210 portD <-- direction right is low num left is high num, keep confusing this since it differs on some platforms and not having used arduino for a while
  DDRB=DDRB | 0b00001111;//only set 8,9,10, 11 as output do not change resst.
  PORTB=0b00000000;//simplified from only turning of 8,9,10,11 to turning of all of portb
  delay(1000);
  eerst=millis();
}

void loop()
{
  nu=millis();
  if(nu-20>=eerst)
  {

```

//forgot to update here PORTB=vals\[state\]; state++; if(state\>7)//resets state { state=0; } } }

**Working Code (might be changed for the long overflow stabilizing), changed variable names to make it clearer for others to read:**

```
unsigned long TimeOfLastStep=0;
unsigned long CurrentTime=0;
int step=0;
byte vals[8]={0b00000001,0b00000011,0b00000010,0b00000110,0b00000100,0b00001100,0b00001000,0b00001001};//made hardcoderd aray to make sure fault wasn't in the cyclic bitshifting

void setup() {
  DDRB=DDRB | 0b00001111;//only set 8,9,10, 11 as output do not change resst.
  PORTB=0b00000000;
  CurrentTime=millis();
}

void loop()
{
  CurrentTime=millis();
  if(CurrentTime-2>=TimeOfLastStep)//increased speed from 20ms delay to 2 ms
  {
    TimeOfLastStep=CurrentTime;//forgot this
    PORTB=vals[state];
    state++;
    if(state>7)//resets state
      {
        state=0;
      }
  }
}

```

# Answer
> 2 votes
I found the problem(s) in my design, everything was right but I forgot to add eerst=nu;(first=now;, used a different language because now is used by the arduino ide). Also I didn't read the datasheet properly and so assume 100step/revolution causing me to use delays which where to large, and so even if it worked the movement would be super slow and possibly missed.

New working code:

```
unsigned long eerst=0;
unsigned long nu=0;
int state=0;
byte vals[8]={0b00000001,0b00000011,0b00000010,0b00000110,0b00000100,0b00001100,0b00001000,0b00001001};//made hardcoderd aray to make sure fault wasn't in the cyclic bitshifting.
//in PortB you have the pins 8,9,10,11,12,13. you start at the back of the byte, so if 0b00000001 then only pin 8 is on. if 0b00000010, then only pin 9 is on, if 0b00000011 then pin 8 and 9 are on. PortB has 8 bits, but only 6 settable pins, so do not change the first 2 bits. you can do it more secure this should be done when using port D since that one is connected to serial. however for simplicity I did not add that code here, you can ask for it and I will probably respond with it.

void setup() { since it differs on some platforms and not having used arduino for a while
  DDRB=DDRB | 0b00001111;//only set 8,9,10, 11 as output do not change resst.
  PORTB=0b00000000; // disabling all port B outputs
  eerst=millis();//eerstm means first, set first to milis to have delay without pausing the code.
}

void loop()
{
  nu=millis();//nu is now, store this lets the code know for how long the arduino ran in milliseconds, needed for non blocking delay, only one now/nu is needed.
  if(nu-2>=eerst)// if 2 milliseconds have passed(have been waited), execute the following code.
  {
    eerst=nu;//reset the non blocking delay timer
    PORTB=vals[state];//Hardcoded values in the array above, this turns on and off pins and is much faster than digital write, selects item at number [state] of aray.
    state++;//go to next state/step
    if(state>7)//resets state
      {
        state=0;//resets state/back to state 0(1 of 8)
      }
  }
}

```

edit: solution was also referenced to in the comments below the post. it was really a problem about having it in mind but forgetting to type something down. anyway I will probably soon start to test with that custom driver don't know how to publish it, but will probably link it back here if I remember it. will be open source probably if I find the proper methods.

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


title: Modify duty cycle of tone on AVR

text:
# Question
Title: Modify duty cycle of tone on AVR
I'm writing a MIDI - to square wave converter designed to interface between a MIDI instrument and a musical Tesla coil. Essentially, this should act like a monophonic MIDI synthesiser, but the requirements are slightly different to most projects:

* I only want to generate (audible frequency) square waves.
* It is *essential* that the pulse on time not exceed a configurable constant value, e.g. 160 microseconds.
* I'd like to map the 'velocity' of a given note to the duty cycle, scaled appropriately.
* Ideally, I'd like to generate envelopes for the pulse width with configurable attack, decay, sustain, release parameters.
* I'd like to write the audio generation code "from scratch" for the sake of my own understanding of how timing registers work.

The gist of what I want is this (untested) sketch, but it obviously doesn't allow for control of the on time.

```
#include <MIDI.h>

MIDI_CREATE_DEFAULT_INSTANCE();
const static int out_pin = 9;

void handleNoteOn(byte channel, byte pitch, byte velocity)
{
    tone(out_pin, pitch);
    digitalWrite(13, HIGH);   // turn the LED on (HIGH is the voltage level)
}

void handleNoteOff(byte channel, byte pitch, byte velocity)
{
    noTone(out_pin);
    digitalWrite(13, LOW);   // turn the LED off
}

void setup() {
  MIDI.setHandleNoteOn(handleNoteOn);
  MIDI.setHandleNoteOff(handleNoteOff);

  MIDI.begin(MIDI_CHANNEL_OMNI);
}

void loop() {
  // put your main code here, to run repeatedly:
  MIDI.read();
}

```

My question is essentially, what the best way to achieve this kind of musical pulse-width control is. The ideas I had were either a) A large number of manual register-sets to bit-bang the required signal out at the highest frequency I can get, probably in the kHz b) Create each pulse using a custom pulseOut function, using timer0 for microsecond delays

I'd also be open to using external analog circuitry, e.g. a voltage controlled pulse shortener.

The load here is an LED, so no special allowances need to be made for its behavior.

# Answer
> 3 votes
I would recommend using a hardware PWM signal generated by Timer 1, or another 16-bit timer if you have more than one (like on the Mega). The 16 bits provide both a decent frequency range and a good time resolution. This should provide jitter-free timings, unlike any software-based method. This will also avoid unduly loading the CPU.

The first thing to do would be to choose the prescaler and the operating mode. These choices will impact both the lowest available frequency and the time resolution. The latter affects the accuracy of the highest-pitched notes. Assuming your Arduino is clocked at 16 MHz, some sensible choices are:

* prescaler = 64, normal PWM
* prescaler = 8, phase correct PWM
* prescaler = 8, normal PWM

| prescaler | PWM mode | time resolution | lowest freq. | lowest note |
| --- | --- | --- | --- | --- |
| 64 | normal | 4 µs | 3.81 Hz | C−1 (MIDI 0) |
| 8 | phase correct | 1 µs | 15.26 Hz | B0 (MIDI 11) |
| 8 | normal | 0.5 µs | 30.52 Hz | B1 (MIDI 23) |

For the sake of having accurate notes, I would go for the lowest time resolution that is compatible with the music you want to play.

Once this is configured, you can control the music by writing to three registers:

* TCCR1A turns the PWM on and off
* the register holding TOP (OCR1A or ICR1, depending on the mode) controls the frequency (the pitch)
* a compare match register (OCR1A or OCR1B, depending on the channel) controls the duration of the pulses

Your program would then need to set the frequency as a function of the requested note, then continuously adjust the pulse duration in order to create the desired envelope while obeying the requested velocity and ensuring the value of 160 µs is never exceeded.

The main code does not even need to be synchronized with the timer: the PWM modes guarantee glitch-free PWM even when you change the duty cycle. Be careful though when changing the frequency: you may get huge glitches when increasing the frequency. It is safer to stop, clear and restart the timer when changing notes.

---
Tags: audio
---