title: CH340G Uploading problem

text:
# Question
Title: CH340G Uploading problem
I've tried to copy CH340G from other schematics and existing Arduino Uno Clones... Searched online & StackExchange but no good :/ My problem is almost the same as this one

Here is my schematic

I can read & send data from the serial monitor

* OS: Win 10 64 Bit
* USB Driver: 3.5.2019.1

**Upload Options:**

* Arduino IDE version: 1.8.12
* Board: Arduino Uno (*also tired nano & nano old bootloader options*)

What I've tried:

* With & without the driver
* Rebooted the computer
* Tried different ports
* Different cables
* In case of IC not working, I've desoldered IC from working UNO
* Changed RX, TX vice versa
* Without R1 & R2
* Different capacitors on C6 and C3 Buuut results are always the same as below

```
avrdude: Version 6.3-20190619
         Copyright (c) 2000-2005 Brian Dean, http://www.bdmicro.com/
         Copyright (c) 2007-2014 Joerg Wunsch

         System wide configuration file is "C:\Program Files (x86)\Arduino\hardware\tools\avr/etc/avrdude.conf"

         Using Port                    : COM3
         Using Programmer              : arduino
         Overriding Baud Rate          : 115200
avrdude: stk500_recv(): programmer is not responding
avrdude: stk500_getsync() attempt 1 of 10: not in sync: resp=0xf3
avrdude: stk500_recv(): programmer is not responding
avrdude: stk500_getsync() attempt 2 of 10: not in sync: resp=0xf3
avrdude: stk500_recv(): programmer is not responding
avrdude: stk500_getsync() attempt 3 of 10: not in sync: resp=0xf3
avrdude: stk500_recv(): programmer is not responding
avrdude: stk500_getsync() attempt 4 of 10: not in sync: resp=0xf3
avrdude: stk500_recv(): programmer is not responding
avrdude: stk500_getsync() attempt 5 of 10: not in sync: resp=0xf3
avrdude: stk500_recv(): programmer is not responding
avrdude: stk500_getsync() attempt 6 of 10: not in sync: resp=0xf3
avrdude: stk500_recv(): programmer is not responding
avrdude: stk500_getsync() attempt 7 of 10: not in sync: resp=0xf3
avrdude: stk500_recv(): programmer is not responding
avrdude: stk500_getsync() attempt 8 of 10: not in sync: resp=0xf3
avrdude: stk500_recv(): programmer is not responding
avrdude: stk500_getsync() attempt 9 of 10: not in sync: resp=0xf3
avrdude: stk500_recv(): programmer is not responding
avrdude: stk500_getsync() attempt 10 of 10: not in sync: resp=0xf3

avrdude done.  Thank you.

Problem uploading to board.  See http://www.arduino.cc/en/Guide/Troubleshooting#upload for suggestions.

```

I appreciate any help, idea, suggestion Regards

# Answer
> 1 votes
The schematic is totally working. My mistake was after burning bootloader, I was uploading code via ISP. If you upload code via ISP, you're removing bootloader.

Thank you everyone who helped me to I wasn't mistaken at schematic and else...

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


# Question
Title: trying to make wemos d1 code modular causes collect2: error: ld returned 1 exit status exit status 1
```
#include "connection.h"

void setup() {
  Serial.begin(115200);
  Funcs::Connect conn;
  conn.connectWifi();
}

void loop() {

}

```

then **connection.h** file:

```
// connection.h

namespace Funcs
{
  class Connect
  {
    public:
      void connectWifi();
  };
}

```

and then **connection.cpp**

```
#include <Arduino.h>
#include <ESP8266WiFi.h>
#include "connection.h"
const char* ssid     = "ssid";
const char* password = "password";

namespace Funcs
{

  void connectWifi() {
    // Connect to WiFi network
    Serial.println();
    Serial.println();
    Serial.print("Connecting to ");
    Serial.println(ssid);

    WiFi.begin(ssid, password);

    while (WiFi.status() != WL_CONNECTED) {
      delay(10);
      Serial.print(".");
    }
    Serial.println("");
    Serial.print("WiFi connected with ip ");
    Serial.println(WiFi.localIP());

  }
}

```

On compiling I get this error:

```
/Library/Arduino15/packages/esp8266/hardware/esp8266/2.5.2/cores/esp8266/HardwareSerial.h:76:
undefined reference to `Funcs::Connect::connectWifi()'

```

collect2: error: ld returned 1 exit status

```
collect2: error: ld returned 1 exit status
exit status 1
Error compiling for board WeMos D1 R1.

```

But I do not have `Funcs::Connect::connectWifi()` in my code, it was in old code.

# Answer
> 0 votes
You are calling Funcs::Connect::connectWifi() right here:

```
conn.connectWifi();

```

since conn is of type Funcs::Connect

But you defined a function Funcs::connectWifi():

```
namespace Funcs
{

  void connectWifi() {

```

where I think you meant to have connectWifi be a member of that Connect class.

```
namespace Funcs
{

  void Connect::connectWifi() {

```

That's not the only issue with your code, you also create the instance in setup and let it go out of scope after calling just the one function. But that's a different kind of error. It's legal code, just probably doesn't do what you want.

---
Tags: programming, c, compilation-errors, cpp
---


title: Arduino parsing Double is incorrect

text:
# Question
Title: Arduino parsing Double is incorrect
Im having some problems with parsing gps coordinates with the arduino ide.

To be honest I want to process the data without a library.

From my sensor I get this String: 4815.98450

The result of String.toDouble(): 4815.9843750

I also parsed it on my own, but i got the same result: (yes this code is not nice ;))

```
char buf[10];
  msg.toCharArray(buf, 19);
  double num = 0.0;

  int c;

  c = buf[0] - '0';
  double num0 = (c * 1000);
  c = buf[1] - '0';
  double num1 = (c * 100);
  c = buf[2] - '0';
  double num2 = (c * 10);
  c = buf[3] - '0';
  double num3 = (c * 1);
  c = buf[5] - '0';
  double num5 = (c * 0.1);
  c = buf[6] - '0';
  double num6 = (c * 0.01);
  c = buf[7] - '0';
  double num7 = (c * 0.001);
  c = buf[8] - '0';
  double num8 = (c * 0.0001);
  c = buf[9] - '0';
  double num9 = (c * 0.00001);
  num = num + num0;
  num = num + num1;
  num = num + num2;
  num = num + num3;
  num = num + num5;
  num = num + num6;
  num = num + num7;
  num = num + num8;
  num = num + num9;

```

Does somebody have a solution for my problems?

Thank you very much :=)

# Answer
> 3 votes
There is no easy solution. The Arduino you are using does not support double precision floating point. The type `double` is just an alias for `float`, which has 24-bit accuracy.

Your program is actually giving you the correct result, as the float closest to 4815.98450 is exactly 4815.984375.

# Answer
> 1 votes
`double` (or float) is just an inappropriate data type.

Perhaps you take int(4815) and float(0.98450) as two numbers?

---

And BTW, I bet from your sensor you don't get a String object.

# Answer
> 0 votes
You can convert this to a long, do your arithmetic, and convert it back to an ASCII-Decimal number:

Remove the decimal point from the string. Convert the remaining string of digits to a long. Now you have the coordinate in binary, in units of the least significant decimal digit; 1 lsb == 0.00001, if you used 5 decimal places.

Manipulate your data however you need to using long integer arithmetic.

Divide the value by 10^ -(# of fraction digits you used). The quotient is the whole number part; the remainder is the fractional part. Print the quotient and a decimal point. Print the remainder padding with zeros to the left as necessary to result in your printing (# of fraction digits you used) total fraction digits.

The output conversion is even easier if you're willing to use sprintf():
Divide the value by 10^ -(# of fraction digits you used), as above. Let's assume 5 places as in your example:

```
char buffer[BIGENOUGH+1];
sprintf(buffer, "%ld.%05ld", value/100000, value%100000);

```

Note that I made two divisions to get the quotient and the remainder and assumed you could tolerate the performance hit. If you're expecting to crank out a lot of values and speed is a factor, you could look up or write a division routine that can return both the quotient and the remainder results from a single division.

Update: @edgar\_bonet points out that the compiler is smart enough to notice this fragment uses both results of the numerically same division and avoids dividing twice after all.

---
Tags: arduino-ide
---


title: Possibility of clean the code?

text:
# Question
Title: Possibility of clean the code?
Good night! Based on stuff I get a bit here and there, came up with a program for an Arduino Audio Selector with shift registers and some features. Working as expected, only missing connecting the relay boads, but that's for future. Since I have a few devices, instead of having to write all, is there anyway of I change for instance a line and then on display show that line?

Thanks. Here's my code, realy big, try to short the part of the shift registers but seems to me it was unstable.

Arduino selector 4x20

# Answer
I see a lot of 'almost' repetitions like :

```
  if (RelaySourceDigi == 7) {
    shifter.setPin(16, LOW);
    shifter.setPin(17, LOW);
    shifter.setPin(18, LOW);
    shifter.setPin(19, LOW);
    shifter.setPin(20, LOW);
    shifter.setPin(21, LOW);
    shifter.setPin(22, HIGH);
    shifter.setPin(23, LOW);
    shifter.write();
    lcd.setCursor(0, 2);
    lcd.write(8);
    lcd.setCursor(2, 2);
    lcd.print("Coaxial 3");
  }

```

Move this to a separate function, and make an argument (or more) of items that vary. This will greatly reduce your code, making it more managable/maintainable.

Below I changed the entire program. Note I didn't check for runtime errors, and it is highly possible I made some copy/paste errors, but it will give you a clue what you can change. As you can see, the program is radically shortened (and more maintainable).

What you need to do is:

* Check each change
* Check for copy/paste errors
* Read a little bit about pointers (e.g. the `&RelaySource` and `*t` constructs)
* Also I highly suggest not to use so many constants, but use `enum`s, to denote the value for each different mode you have. So instead of `case 1`, you can write `case TAPE_1`.
* Split `loop` in smaller functions (e.g. one function per mode).
* I didn't install your libraries but used e.g. #include "LiquidCrystal\_I2C.h" and stubbed all functions (meaning I can call them but they don't do anything, just to check for compiler errors in the main program).
* Also instead of Aux, use a boolean `(true, false)`.
* You see I use a lot of `(state - 1)` constructs. It's common practice to start counting at 0, not at 1, it will make your life easier. Only when displaying a value for a user, add +1. Below the program.

```
//Libraries
#include "LCD.h"
#include "LiquidCrystal_I2C.h"
#include "Shifter.h"

#define SER_Pin 8 //SER_IN 14 on 74HC595
#define RCLK_Pin 9 //L_CLOCK 12 on 74HC595
#define SRCLK_Pin 10 //CLOCK 11 on 74HC595
#define NUM_REGISTERS 3 //how many registers are in the chain
//initaize shifter using the Shifter library
Shifter shifter(SER_Pin, RCLK_Pin, SRCLK_Pin, NUM_REGISTERS);

LiquidCrystal_I2C lcd(0x27, 2, 1, 0, 4, 5, 6, 7, 3, POSITIVE); // Set the LCD I2C address

const int ButtonPinUp = 2;
int ButtonPinUpState = 0;
const int ButtonPinDn = 3;
int ButtonPinDnState = 0;
const int MuteButtonPin = 5;
int MuteButtonPinState = 0;
const int AuxButtonPin = 4;
int AuxButtonPinState = 0;
const int fbutton = 6;
int RelaySource = 1;
int RelaySourceDigi = 1;
int RelayRec = 1;
int RecDigi = 1;
int Mute = 0;
int Mode = 0;
int Aux = 1;
int state = 0;
int old = 0;
int ButtonPoll = 0;

byte opt[8] = {
  0b00000,
  0b01110,
  0b11011,
  0b10001,
  0b10001,
  0b10001,
  0b11111,
  0b00000
};

byte coax[8] = {
  0b00100,
  0b01110,
  0b11111,
  0b10001,
  0b10001,
  0b01110,
  0b00100,
  0b00100
};

byte mut[8] = {
  0b00001,
  0b00011,
  0b00111,
  0b11111,
  0b11111,
  0b00111,
  0b00011,
  0b00001
};

byte outp[8] = {
  B00000,
  B00100,
  B00110,
  B11111,
  B11111,
  B00110,
  B00100,
  B00000
};

byte upp[8] = {
  0b11111,
  0b11111,
  0b11111,
  0b11111,
  0b11111,
  0b11111,
  0b11111,
  0b11111
};

byte inpp[8] {
  0b10000,
  0b10000,
  0b10100,
  0b10110,
  0b11111,
  0b00110,
  0b00100,
  0b00000
};

byte ann[8] {

  0b11111,
  0b10001,
  0b10101,
  0b10101,
  0b10001,
  0b10101,
  0b10101,
  0b11111
};

byte dnn[8] = {
  0b11111,
  0b10011,
  0b10101,
  0b10101,
  0b10101,
  0b10101,
  0b10011,
  0b11111
};

byte too[8] = {
  0b00000,
  0b00100,
  0b00110,
  0b11111,
  0b00110,
  0b00100,
  0b00000,
  0b00000
};

void printAtCursor(int a, int b, const char* c)
{
  lcd.setCursor(a, b);
  lcd.print(c);
}

void setup() {
  lcd.begin(20, 4);
  lcd.backlight();

  byte* list[] = {outp, coax, mut, opt, upp, inpp, ann, dnn, too };
  for (int n = 0; n < 9; n++)
  {
    lcd.createChar(n + 1, list[n]);
  }

  pinMode(fbutton, INPUT);
  pinMode(ButtonPinUp, INPUT);
  pinMode(MuteButtonPin, INPUT);
  pinMode(ButtonPinDn, INPUT);
  pinMode(AuxButtonPin, INPUT);

  for (int n = 11; n < 14; n++)
  {
    pinMode(n, OUTPUT);
  }

  printAtCursor(3, 0, "Digital/Analog");
  printAtCursor(3, 1, "Audio Selector");
  printAtCursor(4, 2, "Built-In DAC");
  printAtCursor(2, 3, "V2.0f (23052020)");
  delay(4000);
  lcd.clear();
}

void setPin(int first, int last, int pin)
{
  for (int n = first; n < last + 1; n++)
  {
    shifter.setPin(n, pin == n ? HIGH : LOW);
  }

  shifter.write();
}

void setLines(int a, int b, const char* t, int x = -1, const char* u = "")
{
    lcd.setCursor(0, a);
    lcd.write(b);
    lcd.setCursor(2, a);
    lcd.print(t);
    if (x != -1)
    {
      lcd.write(x);
      lcd.print(u);
    }
}

void loop()
{
  // shifter.clear(); //set all pins on the shift register chain to LOW
  shifter.write(); //send changes to the chain and display them
  //check button states
  ButtonPinUpState = digitalRead(ButtonPinUp);
  ButtonPinDnState = digitalRead(ButtonPinDn);
  MuteButtonPinState = digitalRead(MuteButtonPin);
  AuxButtonPinState = digitalRead(AuxButtonPin);
  ButtonPoll = digitalRead(fbutton);

  if (AuxButtonPinState == HIGH && RelaySource == 1 && state == 1) {
    lcd.clear();
    Aux           = ~Aux;
    digitalWrite(13, Aux == 0 ? LOW : HIGH);
  }

  if (ButtonPoll == HIGH) {
    state = old + 1;
  }

  lcd.clear(); // Happens in all cases
  switch (state) {
    case 1: // Fall through
    case 2: // Fall through
    case 3: // Fall through
    case 4:
      lcd.setCursor(1, state - 1);
      lcd.write(5);
      old = state;
      break;

    default:
      old = 0;
      break;
  }

  // Assuming state = 1..4
  if (ButtonPinUpState == HIGH)
  {
    lcd.clear();
    int* t = NULL;
    int maxValue = -1;

    switch (state)
    {
      case 1: t = &RelaySource;     maxValue = 8; break;
      case 2: t = &RelayRec;        maxValue = 5; break;
      case 3: t = &RelaySourceDigi; maxValue = 8; break;
      case 4: t = &RecDigi;         maxValue = 4; break;
      default: break;
    }

    *t = min(1, max(maxValue, *t + (ButtonPinUpState == HIGH ? 1 : 0) + (ButtonPinDnState == HIGH ? -1 : 0)));
  }

  if (MuteButtonPinState == HIGH) {
    lcd.clear();
    Mute = (Mute == 0 ? 1 : 0);
    digitalWrite(12, Mute == 0 ? HIGH : LOW);
  }

  // RelaySource
  setPin(0, 7, RelaySource - 1);
  if (RelaySource == 1 && Aux == 0)
  {
    setLines(0, 7, "D", 9, "A:");
  }
  else
  {
    const char* rs1[] = { "Line 1", "Line 2", "CD 1", "CD 2", "Tape 1", "Tape 2/DCC", "Tape 3/DAT", "MD", "MD" };
    setLines(0, 7, rs1[RelaySource - 1]);
  }

  if (RelaySource == 8)
  {
    shifter.setPin(0, LOW); //set pin 1 in the chain(second pin) HIGH
  }

  // RelayRec
  int         rr1[] = { 8      , -1   , 9       , 10      , 11       };
  const char* rr2[] = {"Source", "OFF", "Tape 1", "Tape 2", "Tape 3" };
  const int   rr3[] = { -1     , -1   , 9       , 9       , 9        };
  const char* rr4[] = { ""     , ""   , "2,3"   , "1,3"   , "1,2"    };

  setPin(8, 11, rr1[RelayRec - 1]);
  setLines(1, 6, rr2[RelayRec - 1], rr3[RelayRec - 1], rr4[RelayRec - 1]);

  // RelaySourceDigi
  setPin(16, 23, 17 - RelaySourceDigi);
  if (RelaySource == 1 && Aux == 0)
  {
    lcd.setCursor(7, 0);
    const char* t[] = { "Optical 1", "Optical 2", "Optical 3", "Optical 4", "Coaxial 1", "Coaxial 2", "Coaxial 3", "Coaxial 4" };
    lcd.print(t[RelaySource - 1]);
  }

  const char* t1[] = { "Sony 5-CD", "Sony MD[", "Optical 3", "Optical 4", "Philips CD-R [", "Coaxial 2", "Coaxial 3", "Coaxial 4" };
  const int   t2[] = { 4          , 4         , -1         , -1         , 2               , -1        , -1         , -1          };
  const char* t3[] = { "]"        , "]"       , ""         , ""         , "]"             , ""        , ""         , ""          };
  setLines(2, 8, t1[RelaySourceDigi - 1], t2[RelaySourceDigi - 1], t3[RelaySourceDigi - 2]);

  // RecDigi
  const char* t[] = { "Optical Out1", "Optical Out 2", "Coaxial Out 1", "Coaxial Out2" };
  setPin(12, 15, 11 + RecDigi);
  setLines(3, 6, t[RecDigi - 1]);

  delay(150);
}

```

**Update**

I wanted for myself to see how to clean it fully, so I tried below.

Still check for copy/paste problems, as I didn't execute the sketch (but it compiles without warnings).

Original sketch: 2746 bytes (8%) program storage space, 142 bytes (6%) of dynamic memory Sketch below : 1546 bytes (4%) program storage space, 40 bytes (2%) of dynamic memory.

Conclusion:

* 25% less program storage space used
* 67% less dynamic memory used
* Less lines of code
* Better readability
* Better maintainability
* No (or less) code duplication
* Smaller function complexity
* Less statements (added more to initialization)

Code:

```
//Libraries
#include "LCD.h"
#include "LiquidCrystal_I2C.h"
#include "Shifter.h"

const uint8_t SER_Pin = 8; //SER_IN 14 on 74HC595
const uint8_t RCLK_Pin = 9; //L_CLOCK 12 on 74HC595
const uint8_t SRCLK_Pin = 10; //CLOCK 11 on 74HC595
const uint8_t NUM_REGISTERS = 3; //how many registers are in the chain

Shifter _shifter(SER_Pin, RCLK_Pin, SRCLK_Pin, NUM_REGISTERS);
LiquidCrystal_I2C _lcd(0x27, 2, 1, 0, 4, 5, 6, 7, 3, POSITIVE); // Set the LCD I2C address

enum EMode
{
  RELAY_SOURCE,
  RELAY_REC,
  RELAY_SOURCE_DIGI,
  REC_DIGI,
  LAST_MODE
};

static const uint8_t _buttonPinUp = 2;
bool _buttonPinUpState = false;
static const uint8_t _buttonPinDown = 3;
bool _buttonPinDownState = false;
static const uint8_t _muteButtonPin = 5;
bool _muteButtonPinState = false;
static const uint8_t _auxButtonPin = 4;
bool _auxButtonPinState = false;
static const uint8_t _forwardButton = 6;
uint8_t _relaySource = 0;
uint8_t _relaySourceDigi = 0;
uint8_t _relayRec = 0;
uint8_t _recDigi = 0;
bool _mute = false;
bool _aux = true;
EMode _mode = RELAY_SOURCE;
bool _buttonPoll = false;

static const byte OPT[8]  PROGMEM = {  0b00000,  0b01110,  0b11011,  0b10001,  0b10001,  0b10001,  0b11111,  0b00000 };
static const byte COAX[8] PROGMEM = {  0b00100,  0b01110,  0b11111,  0b10001,  0b10001,  0b01110,  0b00100,  0b00100 };
static const byte MUT[8]  PROGMEM = {  0b00001,  0b00011,  0b00111,  0b11111,  0b11111,  0b00111,  0b00011,  0b00001 };
static const byte OUTP[8] PROGMEM = {  B00000 ,  B00100 ,  B00110 ,  B11111 ,  B11111 ,  B00110 ,  B00100 ,  B00000  };
static const byte UPP[8]  PROGMEM = {  0b11111,  0b11111,  0b11111,  0b11111,  0b11111,  0b11111,  0b11111,  0b11111 };
static const byte INPP[8] PROGMEM = {  0b10000,  0b10000,  0b10100,  0b10110,  0b11111,  0b00110,  0b00100,  0b00000 };
static const byte ANN[8]  PROGMEM = {  0b11111,  0b10001,  0b10101,  0b10101,  0b10001,  0b10101,  0b10101,  0b11111 };
static const byte DNN[8]  PROGMEM = {  0b11111,  0b10011,  0b10101,  0b10101,  0b10101,  0b10101,  0b10011,  0b11111 };
static const byte TOO[8]  PROGMEM = {  0b00000,  0b00100,  0b00110,  0b11111,  0b00110,  0b00100,  0b00000,  0b00000 };

static const byte* const CHAR_LIST[] PROGMEM = {OUTP, COAX, MUT, OPT, UPP, INPP, ANN, DNN, TOO };
static const uint8_t PINS[] PROGMEM = { _forwardButton, _buttonPinUp, _muteButtonPin, _buttonPinDown, _auxButtonPin };

static uint8_t* const    MODE_VALUES[] PROGMEM = { &_relaySource, &_relayRec, &_relaySourceDigi, &_recDigi };
static const uint8_t     MAX_VALUES[] PROGMEM = { 7             , 4         , 7                , 3         };

static const char* const RELAY_SOURCES[] PROGMEM = { "Line 1", "Line 2", "CD 1", "CD 2", "Tape 1", "Tape 2/DCC", "Tape 3/DAT", "MD", "MD" };

static const char* const RELAY_SOURCE_DIGI_1[] PROGMEM = { "Sony 5-CD", "Sony MD[", "Optical 3", "Optical 4", "Philips CD-R [", "Coaxial 2", "Coaxial 3", "Coaxial 4" };
static const int         RELAY_SOURCE_DIGI_2[]         = { 4          , 4         , -1         , -1         , 2               , -1        , -1         , -1          };
static const char* const RELAY_SOURCE_DIGI_3[] PROGMEM = { "]"        , "]"       , ""         , ""         , "]"             , ""        , ""         , ""          };

static const int         RELAY_REC_1[] PROGMEM = { 8      , -1   , 9       , 10      , 11       };
static const char* const RELAY_REC_2[] PROGMEM = {"Source", "OFF", "Tape 1", "Tape 2", "Tape 3" };
static const int         RELAY_REC_3[] PROGMEM = { -1     , -1   , 9       , 9       , 9        };
static const char* const RELAY_REC_4[] PROGMEM = { ""     , ""   , "2,3"   , "1,3"   , "1,2"    };

static const char* const DIGI_RELAY_SOURCES[] PROGMEM = { "Optical 1", "Optical 2", "Optical 3", "Optical 4", "Coaxial 1", "Coaxial 2", "Coaxial 3", "Coaxial 4" };

void printAtCursor(int a, int b, const char* c)
{
  _lcd.setCursor(a, b);
  _lcd.print(c);
}

void setup()
{
  _lcd.begin(20, 4);
  _lcd.backlight();

  for (int n = 0; n < 9; n++)
  {
    _lcd.createChar(n + 1, (byte*) CHAR_LIST[n]);
  }

  for (int n = 0; n < sizeof(PINS) / sizeof(uint8_t); n++)
  {
    pinMode(PINS[n], INPUT);
  }

  for (int n = 11; n < 14; n++)
  {
    pinMode(n, OUTPUT);
  }

  printAtCursor(3, 0, "Digital/Analog");
  printAtCursor(3, 1, "Audio Selector");
  printAtCursor(4, 2, "Built-In DAC");
  printAtCursor(2, 3, "V2.0f (23052020)");
  delay(4000);
}

void setPin(int first, int last, int pin)
{
  for (int n = first; n < last + 1; n++)
  {
    _shifter.setPin(n, pin == n ? HIGH : LOW);
  }

  _shifter.write();
}

void setLines(int a, int b, const char* t, int x = -1, const char* u = "")
{
    _lcd.setCursor(0, a);
    _lcd.write(b);
    _lcd.setCursor(2, a);
    _lcd.print(t);

    if (x != -1)
    {
      _lcd.write(x);
      _lcd.print(u);
    }
}

void ResetShifter()
{
  // _shifter.clear(); //set all pins on the shift register chain to LOW
  _shifter.write(); //send changes to the chain and display them
}

void ReadButtons()
{
  _buttonPinUpState = digitalRead(_buttonPinUp) == HIGH;
  _buttonPinDownState = digitalRead(_buttonPinDown) == HIGH;
  _muteButtonPinState = digitalRead(_muteButtonPin) == HIGH;
  _auxButtonPinState = digitalRead(_auxButtonPin) == HIGH;
  _buttonPoll = digitalRead(_forwardButton) == HIGH;
}

void HandleAuxButton()
{
  if (_auxButtonPinState && (_relaySource == 0) && (_mode == EMode::RELAY_SOURCE))
  {
    _aux = !_aux;
    digitalWrite(13, _aux ? HIGH : LOW);
  }
}

void HandlePollButton()
{
  if (_buttonPoll)
  {
    _mode = (EMode) ((_mode + 1) % EMode::LAST_MODE);
  }
}

void StartLcd()
{
  _lcd.clear(); // Happens in all cases
  _lcd.setCursor(1, (int) _mode);
  _lcd.write(5);
}

void HandleButtonPinUp()
{
  if (_buttonPinUpState)
  {
    static uint8_t* const modeValue = MODE_VALUES[_mode];
    static uint8_t maxValue = MAX_VALUES[_mode];
    *modeValue = min(0, max(maxValue, *modeValue + (_buttonPinUpState ? 1 : 0) + (_buttonPinDownState ? -1 : 0)));
  }
}

void HandleMuteButton()
{
  if (_muteButtonPinState)
  {
    _mute = !_mute;
    digitalWrite(12, _mute ? HIGH : LOW);
  }
}

void ProcessRelaySource()
{
  // RelaySource
  setPin(0, 7, _relaySource);
  if (_relaySource == 0 && !_aux)
  {
    setLines(0, 7, "D", 9, "A:");
  }
  else
  {
    setLines(0, 7, RELAY_SOURCES[_relaySource]);
  }

  if (_relaySource == 7)
  {
    _shifter.setPin(0, LOW); //set pin 1 in the chain(second pin) HIGH
  }
}

void ProcessRelayRec()
{
  setPin(8, 11, RELAY_REC_1[_relayRec]);
  setLines(1, 6, RELAY_REC_2[_relayRec], RELAY_REC_3[_relayRec], RELAY_REC_4[_relayRec]);
}

void ProcessRelaySourceDigi()
{
  setPin(16, 23, 17 - _relaySourceDigi);
  if (_relaySource == 0 && !_aux)
  {
    _lcd.setCursor(7, 0);
    _lcd.print(DIGI_RELAY_SOURCES[_relaySource]);
  }
  setLines(2, 8, RELAY_SOURCE_DIGI_1[_relaySourceDigi - 1], RELAY_SOURCE_DIGI_2[_relaySourceDigi - 1], RELAY_SOURCE_DIGI_3[_relaySourceDigi - 2]);
}

void ProcessRecDigi()
{
  static const char* const t[] PROGMEM = { "Optical Out1", "Optical Out 2", "Coaxial Out 1", "Coaxial Out2" };
  setPin(12, 15, 12 + _recDigi);
  setLines(3, 6, t[_recDigi]);
  delay(150);
}

void loop()
{
  ResetShifter();
  ReadButtons();

  HandleAuxButton();
  HandlePollButton();
  StartLcd();
  HandleButtonPinUp();
  HandleMuteButton();

  ProcessRelaySource();
  ProcessRelayRec();
  ProcessRelaySourceDigi();
  ProcessRecDigi();
}

```
> 2 votes

---
Tags: arduino-uno, arduino-nano, lcd, string, shift-register
---


title: Fading LED with different frequencies

text:
# Question
Title: Fading LED with different frequencies
I have a potentiometer attached to one analog port of arduino (assume A0)
I'm reading the value of that using `input_voltage = analogRead (A0);` which is a value between 0-1023.
So I want to map this value to frequency from 1Hz to 20Hz. Then I want to fade my LED using this frequency.
Tried to doing this map using `int frequency = map (input_voltage, 0, 1023, 1, 20);`
But how can i apply this frequency to LED?
I mean PWM has a constant frequency (about 500Hz). How should I apply frequencies from 1 to 20 to this LED in order to fade it?

# Answer
There is a library in which you can change the frequency

Here is my example code I did long time ago I had the same problem

Get the library from here

Go ahead and try example code there and try to understand too.

**Include the library first to code**

my code

```
void setup() {
  pinMode(13, OUTPUT);
  pinMode(8, OUTPUT);
  digitalWrite(8,LOW);
  Serial.begin(115200);
  InitTimersSafe();
}
void loop() {
  //mapping
  long x = map(analogRead(A0),0,1023,1,20);
  bool b = SetPinFrequencySafe(9,x);
  digitalWrite(13,b);
  pwmWrite(9,127);
  Serial.print(x);
  Serial.print(" Hz ");
  Serial.println(b);
  delay(100);
}

```

Built in led will turn on if the frequency is stetted.

By the way led will turn on in 50% on and 50% off in one cycle in pin 9.

Use only the PWM pins in Arduino 3,9,6 etc.

Now you can change the PWM frequency...

*I just put a led in the female socket in for easiness + terminal in 9 and - terminal in 8 to go to ground that's why I did put pin 8 to low.*
> 0 votes

---
Tags: arduino-uno, pwm, frequency
---


# Question
Title: IR signal: different libs, different bit/byte ordering?
For IR sender at Nano Every (ATMega4809-based) I am using infrared4arduino to send simple remote control codes. I am double-checking those with a Nano-based receiver with IRrecvDumpV2 example from IRremote library but I am receiving something else what I am sending (I think):

The sender has the following code using Infrared4Arduino:

```
   IrSignal* sig=Nec1Renderer::newIrSignal(0,0x906f); // cmd 0x90
   IrSenderPwm::getInstance(true)->sendIrSignal(*sig,1);

```

but the receiver dumps (besides some garbage like 0-bit `JVC` and `SANYO` frames):

```
Encoding  : NEC
Code      : FFF609 (32 bits)
unsigned int  data = 0xFFF609;

```

`0x00` and `0xff` (first 2 bytes of the "packet") are device and its logical complement, those are fine.

The command sent as `0x90` (followed by its logical complement `0x6f`) is decoded as `0xF6` (plus its logical complement `0x09`). Why? Is it an accident that `906f` is `f609` backwards?

What's going on here?

I will try to run both sender and receiver with the same lib (IRremote is not ported to Nano Every) but before I go ahead, better ask. Perhaps I am only doing some IR-beginner's mistake.

# Answer
It is the receiver (IRremote-based) which is decoding bits in reverse order. IRremote and IRLib2 implement the NEC protocol incorrectly (both on sending and receiving sides). More details in the issue report https://github.com/bengtmartensson/Infrared4Arduino/issues/52 .
> 1 votes

---
Tags: infrared
---


# Question
Title: Is there any way to connect my old phone camera with an arduino?
I have an esp8266 wifi module, arduino uno and an old mobile. I was wondering if there is any way by which i could remove the camera from the mobile and connect it with my arduino in order to view video captured by the camera. Is this possible by the hardware which i currently have? Or i will have to buy more hardware? Please let me know if more information is required also give the link of helpful articles.

# Answer
> **Is there any way to connect my old phone camera with an arduino?**

Yes, but it may be a huge amount of work requiring expensive equipment and skills that take decades to acquire.

See Mike's Electric - Interfacing a cheap phone camera module to a PIC32 microcontroller. which is a great video and will give you an idea of what is involved. Note that he's using a 32-bit microcontroller with relatively large RAM on the chip. You might need to use a 32-bit Arduino (Due etc) not one of the 8-bit Arduinos (Uno etc).

Mike is the kind of person who could reverse-engineer a random camera module from an old phone but this isn't a project for a typical Arduino user like you or I.

Since these camera modules cost about $1, it is probably best to look for a camera breakout for Arduino that comes with documentation and software libraries.
> 0 votes

# Answer
An Uno is undersized and underpowered (speed) for this job. Without even considering how to transfer the image, an Uno has nowhere for it to go. The most modest cell phone cameras' images were probably 3 Megapixels, and even assuming 2 bytes of storage per pixel (allowing 5 bits for each of 3 colors), you'd need 6 MB or 6000 KB to store the image. An Uno's RAM is 2K bytes before you subtract whatever RAM its program needs besides room to store the image. Based on those assumptions, an Uno would need another memory, 3000 times the size of its RAM, to hold the image.

Update:

> Is there any possibility that the image is not stored in the arduino rather sent to the server in stream (i.e in small packets)?

I can't imagine why not - at least in theory - but I have no idea what kind of communication hardware might be built into the camera, or if you'd need to develop something on your own. But somehow you'll need to get the image data to the Arduino and in some kind of format you understand and can work with, at least once it gets to the web application. At this point, the critical piece of knowledge would be to know the specs of how the camera delivers image data - how fast, in what format, must the Arduino and the camera interact or does the data just pour out in a flood once started, ... ?

Your first steps will probably need to be to learn how some typical cameras handle this, and to figure out what specific camera you have and how *that* camera works. Then you'll have a much better idea about what it will take to complete your project.
> 0 votes

---
Tags: arduino-uno
---


title: Quiescent Current Analog Input ESP8266

text:
# Question
Title: Quiescent Current Analog Input ESP8266
I'm planning an ESP8266 project, where I connect a soil moisture sensor to an ESP8266 chip (only the chip, not a board like the NodeMCU) (Analog Input). Since the whole setup will be battery-powered, I'm trying to minimize the quiescent current as much as possible. Now my question is: is there a quiescent current through the analog input pin of the ESP8266? and if yes, how large is this current approximately?

Thanks in advance

# Answer
That depends on if you're using a NodeMCU or a "naked" ESP8266.

The NodeMCU has a fixed voltage divider with 220K/100K resistors to ground, contributing about 10 µA to quiescent current (plus the much smaller current caused by the ADC input impedance).

If you're using a NodeMCU you also have to worry about the USB-to-Serial chip and the on-board voltage stabilizer.

The input impedance of the ADC input of a "naked" ESP8266 is (probably) a lot higher, 1 or more MΩ, although it is almost impossible to find definitive numbers.
> 2 votes

---
Tags: esp8266
---


# Question
Title: Getting error invalid conversion from 'const char*' to 'const uint8_t*
I have written this sketch, and I am trying to populate the array of wifi hotspots to set the value in html select using javascript dynamically.

```
#include <Arduino.h>
#include <Hash.h>
#include "ESP8266WiFi.h"
#include <ESPAsyncTCP.h>
#include <ESPAsyncWebServer.h>

const char* ap_ssid     = "ESP8266";
const char* ap_password = "0123456789";

// Create AsyncWebServer object on port 8080
AsyncWebServer ap_server(8080);

const char index_html[] PROGMEM = R"rawliteral(
<!DOCTYPE HTML><html>
<head>
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <style>
    html {
     font-family: Arial;
     display: inline-block;
     margin: 0px auto;
     text-align: center;
    }
    h2 { font-size: 3.0rem; }
    p { font-size: 3.0rem; }
    .units { font-size: 1.2rem; }
    .dht-labels{
      font-size: 1.5rem;
      vertical-align:middle;
      padding-bottom: 15px;
    }
  </style>
  <script>
  var select = document.getElementById("wifi");
  hotspots = %wifi_networks%;
  for(index in hotspots) {
      select.options[select.options.length] = new Option(hotspots[index], index);
  }
</head>
<body>
  <h2>Connect to a Wifi Networks</h2>
  <p>
    <form action="#">
  <label for="wifi">Choose a hotspot to connect:</label>
  <select name="wifi" id="wifi">
    <option value="volvo">None</option>
  </select><br>
  <label for="wifi">Enter password:</label>
  <input type="text"></input>
  <br><br>
  <input type="rescan" value="Rescan">
  <input type="submit" value="Connect">
  </form>
  </p>
</body>

</script>
</html>)rawliteral";

void setup() {
  Serial.print("Setting AP (Access Point)…");
  // Remove the password parameter, if you want the AP (Access Point) to be open
  WiFi.softAP(ap_ssid, ap_password);

  IPAddress IP = WiFi.softAPIP();
  Serial.print("AP IP address: ");
  Serial.println(IP);

  // Print ESP8266 Local IP Address
  Serial.println(WiFi.localIP());

  // Route for root / web page
  ap_server.on("/", HTTP_GET, [](AsyncWebServerRequest * request) {
    request->send_P(200, "text/html", index_html, getWifiHotspots());
  });

  // Start server
  ap_server.begin();
}

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

}

```

But I am geting this error

```
    /Arduino/libraries/ESPAsyncWebServer/src/ESPAsyncWebServer.h:243:10: error:   initializing argument 4 of 'void AsyncWebServerRequest::send_P(int, const String&, const uint8_t*, size_t, AwsTemplateProcessor)' [-fpermissive]

     void send_P(int code, const String& contentType, const uint8_t * content, size_t len,
AwsTemplateProcessor callback=nullptr);
          ^

exit status 1
invalid conversion from 'const char*' to 'const uint8_t* {aka const unsigned char*}' [-fpermissive]

```

# Answer
> 1 votes
In the library ESPAsyncWebServer.h are these two possible function variants defined

```
  void send_P(int code, const String& contentType, const uint8_t * content, size_t len, AwsTemplateProcessor callback=nullptr);
   void send_P(int code, const String& contentType, PGM_P content, AwsTemplateProcessor callback=nullptr);

```

So when using

```
const char index_html[] PROGMEM = R"rawliteral(<YOUR HTML here>)rawliteral";

```

give the compiler the explicit instruction

```
ap_server.on("/", HTTP_GET, [](AsyncWebServerRequest * request) {
  request->send_P(200, "text/html", (const uint8_t*) index_html, getWifiHotspots());
 });

```

The code compiles error free on ArduinoIDE 1.8.12/ESP8266 2.71/ NodeMCUv1 (as not having your definition of getWifiHotspots() I defined it as char)

---
Tags: programming, c, sketch, array, cpp
---


# Question
Title: Bluetooth: read a user provided value and then obtain time from an Android phone
I'm new to Arduino and try to accomplish following 2 things (via Bluetooth module connected to an Android phone):

1. read an integer value provided by user.
2. obtain current time from the phone (the Arduino board itself has no clock module).

As for #1 - I'm able to print to the Bluetooth terminal as follows: `Serial.println("Enter time to wait(in miliseconds): ");`. I see this string on my phone. However I can't manage to read the value from the terminal using `timeToWait = Serial.read();`. I tried many possible combinations, but in the best case I get it in form of chars' ASCII values. So how can I properly read an integer value from the Bluetooth terminal?

As for #2 - is it possible at all, and if yes - how? If it is not possible to obtain current time via BT from Android phone - is it possible to obtain it via BT from a Linux laptop? How?

# Answer
Over a serial port, you are transmitting data byte by byte. If you want to interpret them as numbers, you have to parse the data and assemble the numbers yourself.

You could resort to BLE instead, there you may transmit strings and numbers.
> -1 votes

---
Tags: arduino-uno, serial, bluetooth, android
---


# Question
Title: request for member 'attribute' in 'object', which is of non-class type 'int'
I am trying to create a basic snake game using the arduino UNO along with the MAX72XX module, the LCD module and the analog joystick module. I am wanting to program my program using object orientated programming. I have no experience with C++ so I am struggling quite a bit to understand what the following error is trying to say to me: `request for member 'following_direction' in 'snake[0]', which is of non-class type 'int'`.Here is the full code:

```
#include "LedControl.h"
#include <LiquidCrystal.h>
LedControl lc=LedControl(12,10,11,1);
LiquidCrystal lcd(8, 13, 3, 5, 6, 7);

/*lcd.setCursor(0, 1);
  // print the number of seconds since reset:
  lcd.print(millis() / 1000);*/

class Snake_body
{
  //private:

  public:

    int following_direction;
    int body_length[64];
    int x;
    int y;
    int previous_x;
    int previous_y;

    Snake_body(int x_value, int y_value)
    {
      this->following_direction = 1;
      this->x = x_value;
      this->y = y_value;
      this->previous_y = y_value;
      this->previous_x = x_value;
    }
    /*void configure(int x_value, int y_value)
    {
      this->following_direction = 1;
      this->x = x_value;
      this->y = y_value;
      this->previous_y = y_value;
      this->previous_x = x_value;
    }*/

};

class Power_up
{
  private:

  public:
    virtual void init()
    {
      this->x = 0;
      this->y = 0;
    }

    int x;
    int y;
};

int snake[64];
int snakes_length;

Snake_body *snake_body;
Power_up *power_up;

void setup() {

  lcd.begin(16, 1);

  snakes_length = 1;

  for(int z = 1; z < 64; z++)
  {
  snake[z] = 0;
  }

  snake[0] = new Snake_body(0,0);
  //Snake_body snake[0] = new Snake_body();
  //snake[0].configure(0,0);
  // put your setup code here, to run once:
  lc.shutdown(0,false);
  /* Set the brightness to a medium values */
  lc.setIntensity(0,8);
  /* and clear the display */
  lc.clearDisplay(0);

  pinMode(2, INPUT);
  digitalWrite(2, HIGH);

  Serial.begin(9600);
  power_up->x = random(0, 8);
  power_up->y = random(0, 8);
}

int snake_direction;

void loop()
{
  int x_axis = analogRead(A0);
  int y_axis = analogRead(A1);
  int switcher = digitalRead(2);

   if(x_axis <= 400) //&& x < 7)
   {
     snake[0].following_direction = 0;
     //x += 1;
     //Serial.println("right");
   }

   else if(x_axis >= 600) //&& x > 0)
   {
     snake[0].following_direction = 1;
     //x -= 1;
     //Serial.println("left");
   }

   else if(y_axis <= 400) //&& y > 0)
   {
     snake[0].following_direction = 2;
     //y -= 1;
     //Serial.println("up");
   }

   else if(y_axis >= 600) //&& y < 7)
   {
     snake[0].following_direction = 3;
     //y += 1;
     //Serial.println("down");
   }

  if(snake[0].following_direction == 0 && snake[0].x < 7)
  {
    snake[0].previous_x = snake[0].x;
    snake[0].x += 1;
  }

  else if(snake[0].following_direction == 1 && snake[0].x > 0)
  {
    snake[0].previous_x = snake[0].x;
    snake[0].x -= 1;
  }

  else if(snake[0].following_direction == 2 && snake[0].y > 0)
  {
    snake[0].previous_y = snake[0].y;
    snake[0].y -= 1;
  }

  else if(snake[0].following_direction == 3 && snake[0].y < 7)
  {
    snake[0].previous_y = snake[0].y;
    snake[0].y += 1;
  }

  for(int a = 1; a < 64; a++)
  {
    if(snake[i] != 0)
    {

      snake[i].x = snake[i-1].previous_x;
      snake[i].y = snake[i-1].previous_y;
    }
  }

  lc.setLed(0,power_up->x,power_up->y,true);
  for(int w = 0; w < 64; w++)
  {
    if(snake[w] != 0)
    {
      lc.setLed(0,snake[w].x,snake[w].y,true);
    }
  }

  if(snake[0].x == power_up->x && snake[0].y == power_up->y)
  {
    power_up->x = random(0, 8);
    power_up->y = random(0, 8);

    for(int i = 0; i < 64; i++)
    {
      if(snake[i] == 0)
      {
         Snake_body *snake[i];

         //next_snake_body = new Snake_body();
         snake[i] = new Snake_body(snake[i-1].previous_x, snake[i-1].previous_y);
         //Snake_body next_snake_body;
         //snake[i].configure(snake[i-1].previous_x, snake[i-1].previous_y);
      }
    }
  }
  /*Serial.print("x: ");
  Serial.print(snake.x);
  Serial.println();

  Serial.print("y: ");
  Serial.print(snake.y);
  Serial.println();*/

  if(switcher == 0)
  {
    delay(50);
  }
  else
  {
    delay(100);
  }
  lc.clearDisplay(0);
}

```

the error is coming from this line here:

```
else if(snake[0].following_direction == 3 && snake[0].y < 7)

```

but I think it is also happening at all other lines of which are similar to this one.

I have tried replacing the `.` in `snake[0].following_direction` with a `->` instead but that just caused the error: `base operand of '-> ' is not a pointer`. I have experience programming in java python and a few others but not arduino C++.

# Answer
The problem is indeed in that line:

```
else if(snake[0].following_direction == 3 && snake[0].y < 7)

```

And specifically in:

```
snake[0].following_direction

```

snake is defined as

```
int snake[64];

```

Thus `snake[0]` is of type `int`. And you cannot request the member `following_direction` from type. Since you make new instances with:

```
snake[0] = new Snake_body(0,0)

```

I assume `snake` should be an array of Snake\_body.

So I suggest (at least) change the type to:

```
Snake_body snake[64];

```

Just as a side note, I think one instance of Snake\_body can take up like 16 bytes, and you make 64 of them, this results in 1,024 bytes which is half the memory of an Arduino Uno. Also, sometimes a library takes up some space, so keep this in mind if you are intending to add more libraries/global variables or stack space.

**Update**

Also the following line seems wrong:

```
snake[0] = new Snake_body(0,0);

```

You already created 64 instances of Snake\_body (and assigned to `snake`) after you do my change. So you do not need to do this yourself; actually you cannot, unless you create an array of POINTERS to `Snake_body`.
> 1 votes

---
Tags: arduino-uno, arduino-ide, object-oriented
---


# Question
Title: How do I use a shift register with ioAbstraction?
I’m trying to combine this use of the shift register. With the ioAbstaction library.

But I’m not sure how to read the buttons.

The help in the library seems to suggest more pins for writing than the tutorial for the buttons.

The end goal is to have three LEDs and the buttons connected through the 74HC595 shift register using a minimal number of Ardunio pins.

# Answer
The 74HC595 is a SerialToParallel shift register, mainly to have multiple outputs (SIPO).

You can abuse it to read multiple buttons by multiplexing:

Have one Arduino input pin and several output pins on the shift register to select the current button. This is what the instructables.com is showing.

No idea how that ioAbstraction library might help more than the Arduino-builtin `shiftOut()` function...
> 1 votes

---
Tags: arduino-uno, shift-register
---


title: Reset HC-05 from within Arduino sketch

text:
# Question
Title: Reset HC-05 from within Arduino sketch
I have an HC-05 Bluetooth module attached to an Arduino Mega; the module is paired with a Raspberry Pi and fed data via a python program; there's roughly one send and one receive per second of about 35 bytes.

When I first power up the Arduino / HC-05, it flashes quickly, and then after pairing, it flashes twice every second indicating a successful pair & communication. All is good; data is flowing. Periodically (5 minutes? 3 hrs?) & unpredictably, the communication ends; I'm still trying to troubleshoot this; the python code on the RPi reports a not-helpful `OSError: [Errno 5] Input/output error` on the `available()` method of the `pySerialTransfer` library; though I welcome thoughts on that, I realize that question isn't for this forum.

```
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/home/pi/.local/lib/python3.7/site-packages/pySerialTransfer/pySerialTransfer.py", line 416, in available
    if self.connection.in_waiting:
  File "/home/pi/.local/lib/python3.7/site-packages/serial/serialposix.py", line 467, in in_waiting
    s = fcntl.ioctl(self.fd, TIOCINQ, TIOCM_zero_str)
OSError: [Errno 5] Input/output error

```

The HC-05 module continues to flash as if it's connected, even though it is not, and even if I restart the python program, I'm unable to repair with the HC-05. The only way I can figure out to reconnect to the HC-05 is to power the Arduino / HC-05; then I can reconnect.

So here is the question: is there to reset the HC-05 from within the Arduino sketch? I realize I could attach the VCC to a digital pin to do a full power cycle on the HC-05, but I believe the HC-05 draws on the outer limit of safe current for an Arduino (40ma); I could go thru a relay to do the disconnect, but I wonder if there's a cleaner way with fewer moving parts, or if that is indeed the best way?

Thanks for any guidance!

# Answer
> 0 votes
You could use a logic level MOSFET with low RDSon (e.g. IRLZ44) to switch the supply of the HC-05 and use a digital pin to control it.

---
Tags: serial, bluetooth, hc-05, reset
---


title: Serial Read Data Loss With Arduino Nano

text:
# Question
Title: Serial Read Data Loss With Arduino Nano
I am trying to use Serial reading from a python serial code (which is running on my Jetson Nano) in my project, but in some loop in my code, my data is receiving wrong.

* I use Serial.readBytesUntil() function for interrupt-like reading.
* I use standart blue mini-USB cable for communication.
* My Arduino Nano also connected a nRF24L01 module with SPI.
* Baudrate is 9600 for both devices. I tried 115200 but there is no difference.
* The data loss is about %10 of all loops with both test codes (image-1, image-2).
* There is no positive difference when I use RX/TX pins on both boards with level shifter.
* When I use the test code in my main code with USB connection, the data loss increases %50 of all loops. But Arduino serial monitor is fine like image-3.
* When I use the test code in my main code with RX/TX pins, Arduino serial monitor looks like image-4 and Arduino IDE gives error like image-5.

Here is my receiver test code on my Arduino Nano.

```
void setup() {

  Serial.begin(9600);
  pinMode(LED_BUILTIN, OUTPUT);
  while (!Serial) {}

}

void loop() {
  char buffer[4];
  int deger = 0;
  if (Serial.available() > 0) {
    int size = Serial.readBytesUntil('\n', buffer, 4);

    if (size == 4) {
      Serial.print("deger: ");
      Serial.write(buffer);
      Serial.print("  size: ");
      Serial.print(size);

      // Bytes to integer
      deger = (buffer[1] - 48) * 100 + (int(buffer[2]) - 48) * 10 + (buffer[3] - 48);
      if (buffer[0] == '1') {
        deger = -1*deger; }

      Serial.print(" Sayi: ");
      Serial.println(deger);
      }

    if (deger < 0) {
      digitalWrite(LED_BUILTIN, HIGH);
    }
    else {
      digitalWrite(LED_BUILTIN, LOW);
    }
  }
}

```

And the python serial transmitter test code.

```
import serial

ser = serial.Serial('/dev/ttyUSB0',baudrate=9600,timeout=10)
while True:
    hata = -58

    if hata > 0:
        hata = str(hata)
        if len(hata) == 2:
            hata = '00' + hata
        elif len(hata) == 1:
            hata = '000' + hata
        else:
                hata = '0' + hata    #Pozitive, Added 0
    elif hata < 0:
        hata = -1 * hata
        hata = str(hata)
        if len(hata) == 2:
            hata = '10' + hata
        elif len(hata) == 1:
            hata = '100' + hata
        else:
            hata = '1' + hata    #Negative, Added 1
    else:
        hata = str(hata)
        hata = '000' + hata

    # For every loop, sends 4 character and "\n"  Example: 1058\n
    gonder = hata + '\n'       # For readBytesUntil function
    ser.write(gonder.encode('utf-8'))
    print(gonder.encode('utf-8'))

```

image-1: Arduino test code serial monitor screenshot

image-2: Python test code serial terminal screenshot

image-3: Arduino main project code monitor with USB cable screenshot

image-4: Arduino main project code monitor with RX/TX pins on GPIO screenshot

image-5: Arduino main project code IDE error

So, what did i do wrong? Thank you!

# Answer
You are overflowing your buffer, and also allowing garbage reads.

First you need 5 bytes for your buffer not 4, and you need to ensure it is zeroed out before using it. This is because you are treating it like a C string, which means it must b zero terminated.

Secondly your use of `Serial.readBytesUntil()` is flawed. From the manual:

> The function terminates (checks being done in this order) if the determined length has been read, if it times out (see Serial.setTimeout()), or if the terminator character is detected (in which case the function returns the characters up to the last character before the supplied terminator).

You are sending 5 bytes (`1058\n`) but telling it to read up to 4. Which leaves the `\n` in the buffer. The next time through you read another 4 bytes, which gives you `\n` which is the terminating character.

If you must use `readBytesUntil` then you need to specify a buffer that is bigger than the whole string including the terminator so that the terminator always occurs before the maximum number of bytes read. Including the trailing zero you would thus need at least 6 bytes in your buffer, maybe a couple more "just in case" (one can never tell with Arduino API functions...)

So to roll it all up:

```
  char buffer[8]; // <- Bigger buffer
  memset(buffer, 0, 8); // <- Clear it out
  int deger = 0;
  if (Serial.available() > 0) {
    int size = Serial.readBytesUntil('\n', buffer, 7); // <- Tell it to read more leaving room for the terminating NULL
    ... etc ...

```

```
if (size == 4) {

```
> 1 votes

---
Tags: serial, arduino-nano, uart, python, serial-data
---


title: How to modify values inside a file

text:
# Question
Title: How to modify values inside a file
I am writing a wav file to an SD card on a ESP32 and that requires that every time I append data to the the end of the file I modify the header to set the right size in some fields.

I cannot find how to replace a value inside a file, I tried to write the new values with the seek function but unless I'm missing something looks like this deletes everything after the new value added.

I do not want to create a new file and to delete the old one as I will storing potentially large wav files and looks like wasting resources.

Is there a way to overwrite one value inside a file. I'm using **SDlib** but I'm open to others too.

Here the code I use to create the file and to update it:

```
#include "WavFileWriter.h"

void WavFileWriter::createFile(char const* filename, WavFileHeader* wavFileHeader)
{
  byte headerBuffer[44];
  wavFileHeader->getHeaderData(headerBuffer);
  File file = SD.open(filename, FILE_WRITE);
  file.write(headerBuffer, 44);
  file.close();
}

void WavFileWriter::appendData(char const* filename, WavFileHeader* wavFileHeader, byte* data, int dataLength)
{
  File file = SD.open(filename, FILE_WRITE);
  file.write(data, dataLength);

  byte headerBuffer[44];
  wavFileHeader->setFileSize(file.size());
  wavFileHeader->getHeaderData(headerBuffer);

  file.seek(0);
  file.write(headerBuffer, 44);
  file.close();
}

```

After calling appendData I end up with a file with just the header size (with the right header for a file with data but the data is gone).

# Answer
> 1 votes
The `FILE_WRITE` in SD library is 'append' (for historical reasons)

```
#define FILE_WRITE (O_READ | O_WRITE | O_CREAT | O_APPEND)

```

so use

```
 File file = SD.open(filename, O_WRITE);

```

# Answer
> 0 votes
SD.seek() is the API you're looking for. It allow you to position the read/write pointer within a file. In standard C++ the fseek() API is used.

---
Tags: arduino-uno, sd-card, esp32
---


title: Ethernet shield not getting IP

text:
# Question
Title: Ethernet shield not getting IP
I am just running the below DHCPAddressPrinter sketch in Arduino example to setup EthernetShield with MAC and IP

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

// Enter a MAC address for your controller below.
// Newer Ethernet shields have a MAC address printed on a sticker on the shield
byte mac[] = {
  0x00, 0xAA, 0xBB, 0xCC, 0xDE, 0x02
};

// Initialize the Ethernet client library
// with the IP address and port of the server
// that you want to connect to (port 80 is default for HTTP):
EthernetClient client;

void setup() {
  // Open serial communications and wait for port to open:
  Serial.begin(9600);
  // this check is only needed on the Leonardo:
  while (!Serial) {
    ; // wait for serial port to connect. Needed for Leonardo only
  }

  // start the Ethernet connection:
  if (Ethernet.begin(mac) == 0) {
    Serial.println("Failed to configure Ethernet using DHCP");
    // no point in carrying on, so do nothing forevermore:
    for (;;)
      ;
  }
  // print your local IP address:
  Serial.print("My IP address: ");
  for (byte thisByte = 0; thisByte < 4; thisByte++) {
    // print the value of each byte of the IP address:
    Serial.print(Ethernet.localIP()[thisByte], DEC);
    Serial.print(".");
  }
  Serial.println();
}

void loop() {

 }

```

**After uploading the sketch to arduino,below is the output shown in console**

```
Sketch uses 13,614 bytes (42%) of program storage space. Maximum is 32,256 bytes.
Global variables use 539 bytes (26%) of dynamic memory, leaving 1,509 bytes for local variables. Maximum is 2,048 bytes.

```

**And there is nothing shown in Serial monitor** This is the image of Ethernetshield's some leds glowing after connecting to Router. My router is Binatone Wireless ADSL2+ Router.

**I checked arp -a**,

```
C:\Users\Radhamani>arp -a

Interface: 192.168.1.6 --- 0x3
  Internet Address      Physical Address      Type
  192.168.1.1           6c-fd-b9-24-c6-fe     dynamic
  192.168.1.255         ff-ff-ff-ff-ff-ff     static
  224.0.0.22            01-00-5e-00-00-16     static
  224.0.0.251           01-00-5e-00-00-fb     static
  224.0.0.252           01-00-5e-00-00-fc     static
  239.255.255.250       01-00-5e-7f-ff-fa     static
  255.255.255.255       ff-ff-ff-ff-ff-ff     static

Interface: 192.168.198.1 --- 0xe
  Internet Address      Physical Address      Type
  192.168.198.255       ff-ff-ff-ff-ff-ff     static
  224.0.0.22            01-00-5e-00-00-16     static
  224.0.0.251           01-00-5e-00-00-fb     static
  224.0.0.252           01-00-5e-00-00-fc     static
  239.255.255.250       01-00-5e-7f-ff-fa     static

Interface: 192.168.234.1 --- 0xf
  Internet Address      Physical Address      Type
  192.168.234.255       ff-ff-ff-ff-ff-ff     static
  224.0.0.22            01-00-5e-00-00-16     static
  224.0.0.251           01-00-5e-00-00-fb     static
  224.0.0.252           01-00-5e-00-00-fc     static
  239.255.255.250       01-00-5e-7f-ff-fa     static

```

**Complete result of ipconfig:**

```
Wireless LAN adapter Wi-Fi:
   Connection-specific DNS Suffix  . :
   Link-local IPv6 Address . . . . . : fe80::901:3297:48ad:9e7d%3
   IPv4 Address. . . . . . . . . . . : 192.168.1.6
   Subnet Mask . . . . . . . . . . . : 255.255.255.0
   Default Gateway . . . . . . . . . : 192.168.1.1
Ethernet adapter VMware Network Adapter VMnet1:
   Connection-specific DNS Suffix  . :
   Link-local IPv6 Address . . . . . : fe80::c954:40b2:c8c1:de0%14
   IPv4 Address. . . . . . . . . . . : 192.168.198.1
   Subnet Mask . . . . . . . . . . . : 255.255.255.0
   Default Gateway . . . . . . . . . :
Ethernet adapter VMware Network Adapter VMnet8:
   Connection-specific DNS Suffix  . :
   Link-local IPv6 Address . . . . . : fe80::2837:7e01:c799:d627%15
   IPv4 Address. . . . . . . . . . . : 192.168.234.1
   Subnet Mask . . . . . . . . . . . : 255.255.255.0
   Default Gateway . . . . . . . . . :

```

Serial.println in the program is not printing anything.Looks like Ethernet shield is not getting IP.I am not sure where I am wrong.Please help me to fix this issue

# Answer
Based on the image .. i see that the programmer pins at the back of the shield and the arduino aren't connected properly.. That might be the error or at least happened with me. Apart from that, certain network need to identify the mac address from a look up table and if the shield mac address matches, then only network transactions are allowed. Also i suggest you to drop the virtual machine mac address and networking protocols and try upon the base OS which you have on your computer.
> 2 votes

# Answer
The SD might need disconnecting. Add below to setup().

```
pinMode(10, OUTPUT);
digitalWrite(10, HIGH);

```

Also check the pin assignment for the W5100 (in the Ethernet library).

Cheers!
> 0 votes

# Answer
check the DHCP service of your router is active or not :)
> 0 votes

# Answer
I had the same problem and it had two causes:

1) I couldn't fully insert pins of my shield into the board (ArduinoMega), because if its USB connector. So I connected them with cables. To check for this error, use this code to initialize your Ethernet shield:

```
   Ethernet.begin(mac, ip);
   if (Ethernet.begin(mac) == 0) {
     Serial.println("Failed to configure Ethernet using DHCP");
     Ethernet.begin(mac, ip);

     if (Ethernet.hardwareStatus() == EthernetNoHardware) {
       Serial.println("Ethernet shield was not found.");
     } else if (Ethernet.linkStatus() == LinkOFF) {
       Serial.println("Ethernet cable is not connected.");
     }
   }

```

If this is the case, it will print "Ethernet shield was not found."

2) I'm using this Chinese W510 shield too (the same as on the photo above). Apparently, there's a known bug. Here is the solution: https://forum.arduino.cc/index.php?topic=351477.45

In short: You have to solder 2 resistors between pins 1-2 and 3-6 of the shield's Ethernet connector. No need to unsolder anything.

Works great!
> 0 votes

---
Tags: ethernet
---


# Question
Title: what is causing my esp8266 setup function to reinitialise?
Here is code I have written:

```
#include <stdio.h>
#include <ESP8266WebServer.h>

#define MAX_WIFI_INIT_RETRY 50
#define WIFI_RETRY_DELAY 500

const char* wifi_ssid = "ssid";
const char* wifi_passwd = "password";

ESP8266WebServer http_rest_server(80);

const int numParams = 20;
String params [numParams];

String toString(String my_array[], int size)
{
  String string;
  for (int i = 0; i < size; i++) {
    string = string + ", " + my_array[i];
  }
  return string;
}

int init_wifi() {
  int retries = 0;
  Serial.println("Connecting to WiFi AP..........");
  WiFi.mode(WIFI_STA);
  WiFi.begin(wifi_ssid, wifi_passwd);
  // check the status of WiFi connection to be WL_CONNECTED
  while ((WiFi.status() != WL_CONNECTED) && (retries < MAX_WIFI_INIT_RETRY)) {
    retries++;
    delay(WIFI_RETRY_DELAY);
    Serial.print("#");
  }
  return WiFi.status(); // return the WiFi connection status
}

void readParams(String (& params) [numParams])
{
  int mn = WiFi.scanNetworks();
  for (int i = 0; i < mn; i++)
  {
    //    Serial.println(WiFi.SSID(i).c_str()); // prints name of all hotspots in serial monitor.
    params [i] = WiFi.SSID(i).c_str();
  }
}

void listHotspots() {
  String results = toString(params, sizeof(params));
  Serial.println(results);
  http_rest_server.send(200, "text/plain", results);
}

void config_rest_server_routing() {
  http_rest_server.on("/", HTTP_GET, []() {
    http_rest_server.send(200, "text/html",
                          "Welcome to the ESP8266 REST Web Server");
  });
  http_rest_server.on("/hotspots", HTTP_GET, listHotspots);
}

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

  init_led_resource();

  WiFi.mode(WIFI_STA);
  WiFi.disconnect();
  readParams (params);

  if (init_wifi() == WL_CONNECTED) {
    Serial.print("Connetted to ");
    Serial.print(wifi_ssid);
    Serial.print("--- IP: ");
    Serial.println(WiFi.localIP());
  }
  else {
    Serial.print("Error connecting to: ");
    Serial.println(wifi_ssid);
  }

  config_rest_server_routing();

  http_rest_server.begin();
  Serial.println("HTTP REST Server Started");
}

void loop(void) {
  http_rest_server.handleClient();
}

```

when I access the root url: i.e. `192.168.0.101/` It opens the root page fine, but when I try to open the `192.168.0.101/hotspots` It reboots the ESP8266 until the page stops to make a new attempts and I get nothing in result.

In the serial monitor I am seeing this exception when I try to visit the `ip/hotspot` page .

```
Exception (9):
epc1=0x4020148a epc2=0x00000000 epc3=0x00000000 excvaddr=0x4d2d5456 depc=0x00000000

>>>stack>>>

ctx: cont
sp: 3ffffde0 end: 3fffffc0 offset: 01a0
3fffff80:  3fffdad0 3ffee553 3ffee5a4 40201347
3fffff90:  402086b8 6505a8c0 feefeffe feefeffe
3fffffa0:  3fffdad0 00000000 3ffee5e0 40206614
3fffffb0:  feefeffe feefeffe 3ffe8510 40100479
<<<stack<<<

 ets Jan  8 2013,rst cause:4, boot mode:(3,6)

wdt reset
load 0x4010f000, len 1384, room 16
tail 8
chksum 0x2d
csum 0x2d
v8b899c12
~ld
Connecting to WiFi AP..........
######Connetted to Hometelecom1N5E--- IP: 192.168.0.101
HTTP REST Server Started

```

is it something wrong with the `toString` function ?

# Answer
When a program crashes, you can debug the crash based on the Fatal exception number.

```
 Exception (9)  Unaligned read/write operation addresses
     1. Unaligned read/write Cache addresses
     2. Wild pointers

```

This leads than as Juraj points out to a WD reset:

```
 rst:4     Hardware WDT reset

```

To get the exact part of the code paste the `>>>stack>>>` into the window of the espExeption decoder in the ArduinoIDE. Details how to install and use.

My educated guess is that the heavy use of String class in combination with lot of String operations with the getHotspot function leads to heap corruption and crashes the Esp8266. Try defining fixed char arrays and get rid of the String class to get a stable running system. Post the espExeption decoder result as edit to your question if you thing something else might be fishy
> 1 votes

---
Tags: esp8266, programming, wifi, arduino-setup, cpp
---


# Question
Title: Arduino communication to Raspberry Pi using HC-05
I'm using two HC-05 modules on two Arduino UNO boards. One of my modules connected successfully to a raspberry pi port. However the other doesn't want to connect, but sometimes it does and then randomly disconnects. When I did manage to connect both modules to port on the pi I had code written to send data to the pi and display it in the terminal but only one Arduino data would show up on the pi terminal even though both were sending data. Is there an easier way to connect the modules? I've been using the bluetooth manager tool on the pi

```
void setup() {
 Serial.begin(9600);
 pinMode(8, INPUT); // first sensor input
 pinMode(7, INPUT); // second sensor input
 pinMode(6, INPUT); // third sensor input
 pinMode(5, INPUT); // fourth sensor input

}

void loop()
{

    int sensordata_1 = digitalRead(8); // read status and store it into variable
     {
          if(sensordata_1 == LOW)        //  CAGE 1
          {
            Serial.println("Arduino 1 s1: 1");  //
          }
          else
          {
            Serial.println("Arduino 1 s1: 0");
          }
          delay(200);

    }
}

```

```
void setup() {
 Serial.begin(9600);
 pinMode(8, INPUT); // first sensor input
 pinMode(7, INPUT); // second sensor input
 pinMode(6, INPUT); // third sensor input
 pinMode(5, INPUT); // fourth sensor input

}

void loop()
{

    int sensordata_1 = digitalRead(8); // read status and store it into variable
     {
          if(sensordata_1 == LOW)        //  CAGE 1
          {
            Serial.println("Arduino 2 s1: 1");  //
          }
          else
          {
            Serial.println("Arduino 2 s1: 0");
          }
          delay(200);

    }
}

```

```
import serial
import time

port = serial.Serial("/dev/rfcomm2", baudrate=9600)
port_2 = serial.Serial("
port.flush() # This wil flush any input and output buffer, so it will
#avoid receiving or sending bad data

while True:

    if(port.in_waiting > 0):
        data = port.readline().decode('utf-8').rstrip() # decode will translate
        #the data from unicode to byte
        print(data)

```

# Answer
1. `port_2 = serial.Serial("` is most likely a copy and paste error on your part, but needs to be fixed if you want 2 serial ports to deal with
2. You only read from `port` in your Python while loop without touching `port_2`. This is the reason you only see output from one serial port
3. You should use a robust serial data packet-system. Right now you have no way of ensuring that the data received in Python is corrupt or not. You can easily use the pip-installable Python package pySerialTransfer and compatible Arduino library SerialTransfer.h (installable via the Arduino IDE's Libraries Manager).

For theory behind robust serial communication, check out the tutorials Serial Input Basics and Serial Input Advanced.
> 1 votes

---
Tags: arduino-uno, bluetooth, raspberrypi
---


title: Mount arduino metro mini

text:
# Question
Title: Mount arduino metro mini
I'm using an Arduino Metro Mini (for example https://www.adafruit.com/product/2590) in a project, and want to mount it so the micro USB socket is available through a hole in the case.

Is there an easy way to do this? The main difficulty is that the board has to be mounted end-on to the case, which means you need brackets, which also need standoffs since of course neither side of the board is entirely flat; and the screw holes are at the very end, so no space to spare between them and the case. Etc. If that's not clear, glance at the analogous HDMI mount linked below.

Adafruit sells a complete enclosure (https://www.adafruit.com/product/2709), and there's a similar printable one at https://www.thingiverse.com/thing:936519. I could glue that to the case and then put the mini in there. But that seems like overkill.

For some breakout boards Adafruit has a special panel mount (like the HDMI one at https://www.adafruit.com/product/3121) -- but nothing I see there or elsewhere for the metro mini.

Any better solutions out there? Closest i've seen here is Mounting Arduino in an enclosure

# Answer
What I've done for my projects is to get PC board standoffs of the right height, and use those to mount the board to the bottom of the case.

I measured the height of the USB connector and it's distance from the mounting holes, and calculated where to cut a hole in the side of the case for the USB connector.

I did not look up the USB specification for the depth/clearance of the connector - I just "guesstimated" and it worked fine.
> 1 votes

---
Tags: enclosure
---


title: HC-05 master and slave

text:
# Question
Title: HC-05 master and slave
I have a silly question that came to my mind when communicating between HC-05 and A smartphone, the smartphone is considered as the master, and the HC-05 is considered a slave. master will send data to the slave and then the slave will send these data to the MCU. my question here is that, what is the MCU considered if it is not a master or slave? if I got something wrong, I'll be glad if you correct it for me. thank you

# Answer
You have a misconception about the interfaces involved. Actually we have 2 different interfaces here: Bluetooth and Serial (UART). The HC-05 is a Bluetooth Serial bridge.

The Bluetooth interface has a fixed concept of master and slave. Every connection needs to have only 1 single master. This concept applies only to the communication between HC-05 and the smartphone. It has nothing to do with the MCU itself, because the MCU does not do any Bluetooth communication.

The second interface is the Serial (UART) interface between the HC-05 and the MCU. For this interface there is no concept of master/slave, because it is not needed. Either of them can send independently on their corresponding TX pin and can receive on their RX pin.

These are two totally independent and different communication interfaces. The HC-05 just forwards data between the interfaces.
> 0 votes

---
Tags: serial
---


title: Hardware/software serial for HC-05

text:
# Question
Title: Hardware/software serial for HC-05
can anyone please tell me the whole difference between hardware and software serial for the HC-05. I read UART,USB cable, serial and I was like really confused so what is the difference and advantages between both? thank you...

# Answer
* **Hardware vs Software Serial:** Most microcontrollers/Arduinos have at least 1 hardware Serial interface. That means, that for this Serial interface the actual communication protocol (the transmission and receiving of the actual data) is implemented in dedicated hardware inside the microcontroller (which also means there are fixed pins, where you can connect to them on the board). That way you don't need code for doing the complex communication protocol. Instead the main CPU is only involved to handle the received and to-be-transmitted data, which need to be placed in a buffer register. The dedicated hardware then automatically sends and received the data.

As the number of hardware Serial interfaces is limited and fixed for the Arduino board/microcontroller, it happens, that you need more Serial interfaces, than you have in hardware on your board/in your microcontroller. Then you can use `SoftwareSerial`. That is a library, which handles the complete communication protocol in software, by directly setting and reading the electrical pin states according to the protocol. The advantage is, that you can use this on any digital pins for such an interface. Disadvantage is, that doing such things in software is complex. You can only listen on 1 `SoftwareSerial` interface at a time and the baudrate is limited (depending on the actual used microcontroller, e.g. it's frequency).
* **UART vs Serial:** UART is the technical term for the used communication interface. `Serial` is an Arduino term, which is not used that way in other contexts. The real interface type is UART and the Arduino framework just names that `Serial` to make it simpler.
* **Connecting over USB cable or pins:** Let's take the Arduino Uno as example. It has 1 hardware serial interface. This interface is connected to the pins 0 and 1 (RX and TX), but also internally to an extra chip. That chip handles the USB connection and behaves as a USB-Serial bridge. When communicating with the Serial Monitor in the Arduino IDE, you are actually using this USB-Serial bridge to talk to the microcontroller on the Arduino. But you could also use the RX/TX pins to do that.
> 0 votes

# Answer
Hardware serial uses pins 0/1 on the Uno. You can't change those pins. Those pins are also the pins that are used to communicate with your computer. You can use hardware serial on those pins to communicate with the HC-05 *only* if you don't want to communicate with your computer.

SoftwareSerial can be used on any pins so can be used at the same time as the hardware serial for communicating with your computer. However SoftwareSerial is somewhat limited in what it can do.

Bigger boards (such as the Mega) usually have more than one hardware serial port. These are connected to the TX1/RX1, TX2/RX2 etc pins. These are the preferred method of connecting to external serial devices since they work more reliably that SoftwareSerial and concurrently with the computer's USB connection.
> 0 votes

---
Tags: serial, hardware, uart, hc-05, software
---


# Question
Title: Wire.endTransmission() hangs, but only, if wire.begin(); is called with an address (MKR WiFi 1010)
This code runs without issues, scoped and seen from serial output:

```
#include <Wire.h>

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

  while (!Serial);
}

void loop()
{
  Serial.println("1");
  Wire.beginTransmission(8);
  Serial.println("2");
  Wire.write(0x1);
  Serial.println("3");
  delay(100);
  Wire.endTransmission();
  delay(100);
  Serial.println("4");
  delay(500);
}

void receiveEvent(int howmany)
{
  delay(100);
}

```

This one hangs on Wire.endtransmission():

```
#include <Wire.h>

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

  while (!Serial);
}

void loop()
{
  Serial.println("1");
  Wire.beginTransmission(8);
  Serial.println("2");
  Wire.write(0x1);
  Serial.println("3");
  delay(100);
  Wire.endTransmission();
  delay(100);
  Serial.println("4");
  delay(500);
}

void receiveEvent(int howmany)
{
  delay(100);
}

```

The problem starts as soon as I assign an address in Wire.begin(). As I understand, a slave is also allowed to send data and temporarily becoming a master when addressing another device.

# Answer
> 0 votes
While the wire library supports multi-master for AVR, it doesn't for ATSAMD.

Temporary promotion to master is disabled when given a slave address, so the program will hang on wire.endTransmission().

# Answer
> 0 votes
> I want to push data from the slaves to the master immediately when they receive said data.

So that means, that each slaves becomes master directly after it has received data from the MKR. This is still a multi-master setup, even while you are avoiding collisions through a fixed protocol. The `Wire` library does not support multi-master.

But I also don't understand, why you would need this. Your protocol does this: The MKR sends data to a slave (triggering it and maybe also sending some commands). Then the slave should send data back to the master. Then the transmission ends. This is normally done in I2C with just one master. The master does a master write (via `Wire.endTransmission()` and sends some command data to the slave. The slave will prepare the data, that the master requested, in it's buffer. Then the master will start a master read (via `Wire.requestFrom()`) which reads the data from the slave.

So you don't need a multi-master setup for this. It does exactly, what you described, but with only one master.

---
Tags: i2c, mkr1010
---


# Question
Title: config file for Arduino Uno installed on Raspberry PI
The Arduino code shown runs successfully. My problem is configuring the Arduino IDE so it fits within the Raspberry Pi window. The second image, the built-in serial port /dev/ttyAMA0, is produced. It is blank.

The Arduino Menu bar cannot be accessed. Therefore, the **Tools** button and other buttons for running the code are not available. The user can adjust the width of the Arduino IDE window but cannot move it around the screen or up or down.

The /boot/config file is setup up for a Adafruit 5" Backback monitor. No other app, Thonny Pi, or the terminal has these problems.

It appears to me that the config file needs some work. That is only a guess.

```
Any suggestions will be greatly appreciated.

```

# Answer
> 1 votes
In Linux you can move things around in different ways. For example:

1. Hold ALT and click and drag anywhere in the window. The whole window will move and you can get to the edge to resize it.
2. Press ALT-Space then M and you can use the cursor keys to move the window around
3. Press ALT-Space then X and it will maximise the window to the screen size

# Answer
> 0 votes
What you can do is set the default IDE window size by editing preferences.txt:

Click the link on the line following File \> Preferences \> More preferences can be edited directly in the file.

This will open the Arduino15 (or similar folder name) folder.

Close the Arduino IDE.

Open the file preferences.txt in a text editor

Change the editor.window.height.default and editor.window.width.default properties to your desired window size.

Save the file.

---
Tags: arduino-uno, raspberrypi
---


# Question
Title: How long does it take for a servo to change rotation?
I have an Arduino Uno and a Micro Servo 9g A0090 servo.

Given that Servo.read() simply returns the *last* value written to the servo I guess there is no way to query a servo's actual position.

If I can't query the servo, how do I know that the servo rotated to the position of my last write() call?

Rotating from 0 to 180 will take longer than rotating from 0 to 10. How do people normally handle this scenario? Perhaps I just time how long it takes to go from 0 to 180 and then always call delay() afterward to give the servo time to complete its rotation?

# Answer
Normal servos don't provide any feedback. Their speed depends on the servo's specs and the load.

You could measure the time it takes to rotate a certain angle and use that to calculate the time, then add some safety margin. But if the load isn't constant, the times will be off.
You could change the position slowly, but that still doesn't guarantee that the servo will do what you told it to.

If you want to know servos's position, you need a servo that outputs it. There are servos that expose the signal from their internal potentiometer.

Adafruit sells them and has a useful guide about them.

You can also modify a normal servo yourself, by attaching a feedback wire to the potentiometer's wiper pin.
> 7 votes

# Answer
I can imagine several ways how to do it:

* You can wait some specific time. How long it takes to rotate from 0 to 180. But it'll wait for much longer for small angles than it's necessary.
* Better aproach would be to compute delay based on angle (maybe even on servo power supply voltage)
* Another way would be measuring servo's power supply current.
* You can use some rotary encoder. But some extra gears might be needed to be able to detect position fine enough.
* You can "hack" into the servo's electronic and get the position - it's usually voltage divider (potentiometer). But it might introduce some extra interferences and servo might be fuzzy or unstable...
> 1 votes

# Answer
For 9g servo .10 sec for 60 degree rotation. For mg995 .18 to .19 sec for 60 degree rotation. For servo 3003 0.19 to 0.20 or 60 degree rotation.

You can check specification for other servos. I gave for common servos above.

Hope this help.
> 0 votes

---
Tags: arduino-uno, servo
---


# Question
Title: Arduino Atmega32U with nRF51 BLE by Adafruit limited to 5 second update rate?
Would like to ask for assistance with the code below. It's the Adafruit Bluefruit Atmega32U LE module with Adafruit's Arduino IDE example "heart-rate monitor" sketch. The code uses the hardware SPI setup with Adafruit's BLE code between the Atmega32U and the nRF51822 using AT Commands built into a BLE stack by Adafruit.

It works at the same speed in real-time on the PC's Arduino IDE USB serial terminal and also on the Android phone's nRF Connect app or any other BLE app that can read "notifications".

**Problem: If remove the module from the PC's USB (thus the serial stopped and only using BLE) the update rate on the BLE Android app slows down to 5 second intervals compared to the near real-time speed while connected to USB.** I tried many things, including commenting out the Serial commands in the void loop() and also the delay(), but no change. As if the BLE stack by Adafruit would have a update period limitation. According to Adafruit, they do not give access to to their BLE stack. But I could possibly load another BLE stack on this nRF51822 chip. Also I do have the Adafruit Sniffer with Wireshark, but not an expert using it.

How can I get less than 1 second update rates? The data stream is not in 1 second intervals. Maybe 10-15 seconds between readings, but I need it updated within 1 second of being read from the sensor.

https://learn.adafruit.com/adafruit-feather-32u4-bluefruit-le?view=all

```
#include <Arduino.h>
#include <SPI.h>
#include "Adafruit_BLE.h"
#include "Adafruit_BluefruitLE_SPI.h"
#include "Adafruit_BluefruitLE_UART.h"

#include "BluefruitConfig.h"

#if SOFTWARE_SERIAL_AVAILABLE
  #include <SoftwareSerial.h>
#endif

// Create the bluefruit object, either software serial...uncomment these lines
/*
SoftwareSerial bluefruitSS = SoftwareSerial(BLUEFRUIT_SWUART_TXD_PIN, BLUEFRUIT_SWUART_RXD_PIN);

Adafruit_BluefruitLE_UART ble(bluefruitSS, BLUEFRUIT_UART_MODE_PIN,
                      BLUEFRUIT_UART_CTS_PIN, BLUEFRUIT_UART_RTS_PIN);
*/

/* ...or hardware serial, which does not need the RTS/CTS pins. Uncomment this line */
// Adafruit_BluefruitLE_UART ble(BLUEFRUIT_HWSERIAL_NAME, BLUEFRUIT_UART_MODE_PIN);

/* ...hardware SPI, using SCK/MOSI/MISO hardware SPI pins and then user selected CS/IRQ/RST */
Adafruit_BluefruitLE_SPI ble(BLUEFRUIT_SPI_CS, BLUEFRUIT_SPI_IRQ, BLUEFRUIT_SPI_RST);

/* ...software SPI, using SCK/MOSI/MISO user-defined SPI pins and then user selected CS/IRQ/RST */
//Adafruit_BluefruitLE_SPI ble(BLUEFRUIT_SPI_SCK, BLUEFRUIT_SPI_MISO,
//                             BLUEFRUIT_SPI_MOSI, BLUEFRUIT_SPI_CS,
//                             BLUEFRUIT_SPI_IRQ, BLUEFRUIT_SPI_RST);

// A small helper
void error(const __FlashStringHelper*err) {
  Serial.println(err);
  while (1);
}

/* The service information */

int32_t hrmServiceId;
int32_t hrmMeasureCharId;
int32_t hrmLocationCharId;
/**************************************************************************/
/*!
    @brief  Sets up the HW an the BLE module (this function is called
            automatically on startup)
*/
/**************************************************************************/
void setup(void)
{
  while (!Serial); // required for Flora & Micro
  delay(500);

  boolean success;

  Serial.begin(115200);
  Serial.println(F("Adafruit Bluefruit Heart Rate Monitor (HRM) Example"));
  Serial.println(F("---------------------------------------------------"));

  randomSeed(micros());

  /* Initialise the module */
  Serial.print(F("Initialising the Bluefruit LE module: "));

  if ( !ble.begin(VERBOSE_MODE) )
  {
    error(F("Couldn't find Bluefruit, make sure it's in CoMmanD mode & check wiring?"));
  }
  Serial.println( F("OK!") );

  /* Perform a factory reset to make sure everything is in a known state */
  Serial.println(F("Performing a factory reset: "));
  if (! ble.factoryReset() ){
       error(F("Couldn't factory reset"));
  }

  /* Disable command echo from Bluefruit */
  ble.echo(false);

  Serial.println("Requesting Bluefruit info:");
  /* Print Bluefruit information */
  ble.info();

  // this line is particularly required for Flora, but is a good idea
  // anyways for the super long lines ahead!
  // ble.setInterCharWriteDelay(5); // 5 ms

  /* Change the device name to make it easier to find */
  Serial.println(F("Setting device name to 'Bluefruit HRM': "));

  if (! ble.sendCommandCheckOK(F("AT+GAPDEVNAME=Bluefruit HRM")) ) {
    error(F("Could not set device name?"));
  }

  /* Add the Heart Rate Service definition */
  /* Service ID should be 1 */
  Serial.println(F("Adding the Heart Rate Service definition (UUID = 0x180D): "));
  success = ble.sendCommandWithIntReply( F("AT+GATTADDSERVICE=UUID=0x180D"), &hrmServiceId);
  if (! success) {
    error(F("Could not add HRM service"));
  }

  /* Add the Heart Rate Measurement characteristic */
  /* Chars ID for Measurement should be 1 */
  Serial.println(F("Adding the Heart Rate Measurement characteristic (UUID = 0x2A37): "));
  success = ble.sendCommandWithIntReply( F("AT+GATTADDCHAR=UUID=0x2A37, PROPERTIES=0x10, MIN_LEN=2, MAX_LEN=3, VALUE=00-40"), &hrmMeasureCharId);
    if (! success) {
    error(F("Could not add HRM characteristic"));
  }

  /* Add the Body Sensor Location characteristic */
  /* Chars ID for Body should be 2 */
  Serial.println(F("Adding the Body Sensor Location characteristic (UUID = 0x2A38): "));
  success = ble.sendCommandWithIntReply( F("AT+GATTADDCHAR=UUID=0x2A38, PROPERTIES=0x02, MIN_LEN=1, VALUE=3"), &hrmLocationCharId);
    if (! success) {
    error(F("Could not add BSL characteristic"));
  }

  /* Add the Heart Rate Service to the advertising data (needed for Nordic apps to detect the service) */
  Serial.print(F("Adding Heart Rate Service UUID to the advertising payload: "));
  ble.sendCommandCheckOK( F("AT+GAPSETADVDATA=02-01-06-05-02-0d-18-0a-18") );

  /* Reset the device for the new service setting changes to take effect */
  Serial.print(F("Performing a SW reset (service changes require a reset): "));
  ble.reset();

  Serial.println();
}

/** Send randomized heart rate data continuously **/
void loop(void)
{
  int heart_rate = random(50, 100);

  //Serial.print(F("Updating HRM value to "));
  //Serial.print(heart_rate);
 // Serial.println(F(" BPM"));

  /* Command is sent when \n (\r) or println is called */
  /* AT+GATTCHAR=CharacteristicID,value */
  ble.print( F("AT+GATTCHAR=") );
  ble.print( hrmMeasureCharId );
  ble.print( F(",00-") );
  ble.println(heart_rate, HEX);

  /* Check if command executed OK */
 // if ( !ble.waitForOK() )
 // {
   // Serial.println(F("Failed to get response!"));
  //}

  /* Delay before next measurement update */
 // delay(1000);
}

/////////////////AND BELOW IS THE BluefruitConfig.h TAB in ARDUINO IDE --This is a separate file under a new tab in the IDE////////////////..

    // COMMON SETTINGS
// ----------------------------------------------------------------------------------------------
// These settings are used in both SW UART, HW UART and SPI mode
// ----------------------------------------------------------------------------------------------
#define BUFSIZE                        128   // Size of the read buffer for incoming data
#define VERBOSE_MODE                   true  // If set to 'true' enables debug output

// SOFTWARE UART SETTINGS
// ----------------------------------------------------------------------------------------------
// The following macros declare the pins that will be used for 'SW' serial.
// You should use this option if you are connecting the UART Friend to an UNO
// ----------------------------------------------------------------------------------------------
#define BLUEFRUIT_SWUART_RXD_PIN       9    // Required for software serial!
#define BLUEFRUIT_SWUART_TXD_PIN       10   // Required for software serial!
#define BLUEFRUIT_UART_CTS_PIN         11   // Required for software serial!
#define BLUEFRUIT_UART_RTS_PIN         8    // Optional, set to -1 if unused

// HARDWARE UART SETTINGS
// ----------------------------------------------------------------------------------------------
// The following macros declare the HW serial port you are using. Uncomment
// this line if you are connecting the BLE to Leonardo/Micro or Flora
// ----------------------------------------------------------------------------------------------
#ifdef Serial1    // this makes it not complain on compilation if there's no Serial1
  #define BLUEFRUIT_HWSERIAL_NAME      Serial1
#endif

// SHARED UART SETTINGS
// ----------------------------------------------------------------------------------------------
// The following sets the optional Mode pin, its recommended but not required
// ----------------------------------------------------------------------------------------------
#define BLUEFRUIT_UART_MODE_PIN        12    // Set to -1 if unused

// SHARED SPI SETTINGS
// ----------------------------------------------------------------------------------------------
// The following macros declare the pins to use for HW and SW SPI communication.
// SCK, MISO and MOSI should be connected to the HW SPI pins on the Uno when
// using HW SPI.  This should be used with nRF51822 based Bluefruit LE modules
// that use SPI (Bluefruit LE SPI Friend).
// ----------------------------------------------------------------------------------------------
#define BLUEFRUIT_SPI_CS               8
#define BLUEFRUIT_SPI_IRQ              7
#define BLUEFRUIT_SPI_RST              4    // Optional but recommended, set to -1 if unused

// SOFTWARE SPI SETTINGS
// ----------------------------------------------------------------------------------------------
// The following macros declare the pins to use for SW SPI communication.
// This should be used with nRF51822 based Bluefruit LE modules that use SPI
// (Bluefruit LE SPI Friend).
// ----------------------------------------------------------------------------------------------
#define BLUEFRUIT_SPI_SCK              13
#define BLUEFRUIT_SPI_MISO             12
#define BLUEFRUIT_SPI_MOSI             11

```

# Answer
The "verbose" error check mode for debug in the "BluefruitConfig.h" tab slowed down the flow of BLE data. I changed it from "true" to "false" to turn it off.

```
#define VERBOSE_MODE true  // If set to 'true' enables debug output

```
> 0 votes

---
Tags: spi, adafruit, atmega32u4, ble, nrf51
---


# Question
Title: Serial printing from flash memory (F() macro, PROGMEM, sprintf_P, SPTR)
I have been testing various techniques on an Arduino Uno for serial printing from flash memory instead of RAM. At the same time, I have been using the freeMemory() function from Adafruit.

I created a program that prints the word "test", with various methods:

### Simple print:

```
Serial.print("test");
Serial.print(freeMemory());

```

This call reports free RAM = 2267

### Using the F() Macro:

```
Serial.print(F("test"));
Serial.print(freeMemory());

```

This call reports free RAM = 2299

### Using sprintf\_P()

```
char buf[100];
sprintf_P(buf,PSTR("test"));
Serial.print(buf);
Serial.print(freeMemory());

```

This call reports free RAM = 2267

### Using strcpy\_P()

```
 char buf[100];
 strcpy_P(buf, (PGM_P)F("test"));
 Serial.print(buf);
Serial.print(freeMemory());

```

This call reports free RAM = 2267

### Using strcpy\_P and const char\[\] PROGMEM

```
char buf[100];
const char buff[] PROGMEM = "test";
strcpy_P(buf, buff);
Serial.print(buf);
Serial.print(freeMemory());

```

This call reports free RAM = 2267

The basic point of this question is to gather ***all the possible flash memory printing*** techniques. Also it would be really useful if you could explain in detail what exactly each of the keywords F(), (PGM\_P)F, PSTR, const PROGMEM does.

**IMPORTANT EDIT, 1:**

Depending on where and how I use the call `Serial.print(freeMemory());` the results change. For example, at the last example (PROGMEM, strcpy\_P) when I included another `Serial.print(freeMemory());` before the call of the printing functions, then both freeMemory() calls report 2299!

Another interesting problem is that the freeMemory() reports 2299 as freeRam, while the SRAM of my Arduino Uno is only 2 kbytes.

**EDIT 2:**

Following the suggestion in comments, I changed "test" to "testtesttesttesttesttesttesttesttesttesttesttesttesttesttesttest". Now all different methods report a free ram of 2299, including the simple `Serial.print()`.

freeMemory():

```
#ifdef __arm__
// should use uinstd.h to define sbrk but Due causes a conflict
extern "C" char* sbrk(int incr);
#else  // __ARM__
extern char *__brkval;
#endif  // __arm__
int freeMemory() {
  char top;
#ifdef __arm__
  return &top - reinterpret_cast<char*>(sbrk(0));
#elif defined(CORE_TEENSY) || (ARDUINO > 103 && ARDUINO != 151)
  return &top - __brkval;
#else  // __arm__
  return __brkval ? &top - __brkval : &top - __malloc_heap_start;
#endif  // __arm__
}

```

# Answer
> 7 votes
First, the freeMemory() function that you used from Adafruit was originated from a GitHub repository.

I don't know about the `__arm__` implementation, but for the AVR one, it is incomplete for handling the corner case when the program does not use the `malloc()` function. If your program never uses `malloc()`, the formula used in `freeMemory()` will produce the wrong result. A simple corrected version for AVR that I used is here:

```
extern unsigned int __heap_start;
extern char *__brkval;

int freeMemory() {
  char top_of_stack;

  if (__brkval == 0) {
    Serial.println(((int)&top_of_stack - (int)&__heap_start));
  } else {
    Serial.println((int)&top_of_stack - (int)__brkval);
  }
}

```

> explain in detail what exactly does each of the keywords F(), (PGM\_P)F, PSTR, const PROGMEM.

### PSTR("string literal")

PSTR came into Arduino from part of *avr-libs* (a C library) defined in avr/pgmspace.h. It is actually a macro, not a function as many think it was, and is defined as:

```
#define     PSTR(s)   ((const PROGMEM char *)(s))

```

It looks a little bit intimidating, but it is actually quite simple. It not only tells the *avr-gcc* that the string literal `s` should be kept in program memory (i.e., flash memory in the case of Arduino), but it allows the program to convert it into a `const char *s PROGMEM` variable, so that it can be pass around into some PROGMEM-aware functions as a parameter.

```
 // This is a PROGMEM-aware function in C
 printMsg_P(const char* str) {
     char buf[strlen_P(str)+1];
     strcpy_P(buf, str);
     puts(buf);
 }

 // This handles the normal string array function
 printMsg(const char* str) {
     puts(str);
 }

```

### F("string literal")

`F()` is also a macro, but it is not part of the `avr/progmem.h`. It is actually part of the *String* class defined in WString.h together with a definition of a class called `__FlashStringHelper`:

```
class __FlashStringHelper;
#define F(string_literal) (reinterpret_cast<const __FlashStringHelper *>(PSTR(string_literal)))

```

To understand the `F()` macro and the difference between `F()` and `PSTR()` take a little bit explanation.

As you can see from the definition of `F()`, it casts a string literal into a `const char*` variable using `PSTR()`, and then recast it into a class `__FlashStrngHelper`. If you further look at the `__FlashStringHelper`, it is actually an empty class without any construct or method. It is literally empty, so why is this useful? And why can't it just pass the string literal around by just using `PSTR()`?

This has to do with C++'s function overload. Function overload is a feature of C++ where multiple methods could have the same function name, but each with different parameters. Within all the `Serial.print()` methods, there is a method `Serial.print(const char* str)` that will take in a string literal and print it to serial monitor, but it is not PROGMEM-aware. If you pass in a PROGMEM string literal `Serial.print(PSTR("string literal"));`, the same method will accept what you pass in because it meet the type checking (remember `PSTR` is actually `const char*`), but it will not print out the correct string for `PSTR("string literal")`, because it simply expecting a normal string.

In C, as we see before, we solve the problem by using two functions with different names for handling normal string and PROGMEM string, but `Serial` is a C++ class. It needs another function overloaded method to be PROGMEM-aware, and PSTR() is clearly not the solution as we just mentioned.

*WSting.h* and *Print.cpp* create an overload method that is PROGMEM-aware by accepting a class as parameter, so that you can pass a `F()` wrapped string literal which has a data type of class `__FlashStringHelper` into the `Serial.print()` and get the print out correctly from program memory. See the source code yourself.

```
Serial.print(const __FlashStringHelper *ifsh)

```

So in summary, the `F()` and `PSTR()` are alike. Both are telling the compiler to keep the string literal in the program memory, and allow the string literal to be pass around into some function as parameter. But it was designed for different purpose from different programming paradigm (C versus C++). `F()` is `Serial.print()`-friendly, while `PSTR()` is not. If you are getting `PSTR()` in a function and yet you want to send it to `Serial.print()`, you will have to explicitly cast it into `__FlashStringHelper` like this:

```
Serial.print((__FlashStringHelper*)PSTR("test"));

```

### PGM\_P

`PGM_P` is a macro defined as:

```
#define     PGM_P   const char *

```

Whether you want to use `PGM_P` or `const char *` is a personal preference. For example, this is copy from *PROGMEM* (Arduino reference):

```
const char *const string_table[] PROGMEM = {string_0, string_1, string_2, string_3, string_4, string_5};

```

can be written as:

```
PGM_P const string_table[] PROGMEM = {string_0, string_1, string_2, string_3, string_4, string_5};

```

This is a lengthy explanation, but I hope this will help with better understanding the subject and therefore be able to use the PROGMEM and all the associated macros effectively.

# Answer
> 3 votes
> explain in detail what exactly does each of the keywords F(), (PGM\_P)F, PSTR, const PROGMEM.

* `F()` wraps the string literal in `PSTR(...)` and then casts it to `__FlashStringHelper`. This forces it to remain in flash and also gives it a type that the Arduino core can identify as a string in flash for overloading.
* `PGM_P` is a "Pointer to ProGraM mememory". This is the type that all the `_P` variants of functions require. It's basically `const char *` provided by `avr/pgmspace.h`
* `const PROGMEM` is actually two things. `const` means you're not changing the value, and `PROGMEM` is another name for `__ATTR_PROGMEM__` which itself is an alias for `__attribute__((__progmem__))` which is a flag for the compiler to tell it to keep the variable in flash and not copy it to RAM.

So `F()` and `PGM_P` are used when you are passing a string literal to a function that expects one of those formats. `PROGMEM` is used when you're setting up a constant "variable" (oxymoron there, I know...) that points to data in flash.

---
Tags: atmega328, memory-usage, memory, sram
---