# Question
Title: how to prevent IR signal to go through 3d printed plastic?
I'm working on two arduino (one a dock, the other one on a robot) communicating through a IR to let the latter know about its location.

I 3D printed a piece which goal was to channel the 3 IR led lights, to prevent them from overlapsing (exactly in the same manner as the Kobuki.

For a reason I don't know, the IR signals seem to go through the 3D printed piece which doesn't seem to let visible light through.

I known that there is no 100% absorbant materials, and I know "black for visible lights" doesn't necessarily mean "black for IR lights".

I think my problem is more related to my lack of experience in the field. My question is : why do I get signals from a IR led channeled toward a location I am not in ?

Patently, it means my light channels are not channeling light.

Therefore, better : How can I make a better (and cheap) channel for IR light ?

The piece I 3D printed is grey (silvery like I guess)

edit : to prevent incomprehension, i would like to clarify "channel". What I mean is to block all light "not going" in the right direction, whatever happens to that light. I apologize if it is not the word I should have used.

# Answer
You can not use common modulation remote control receivers as they contain an ACG feature which will likely "turn up the volume" until it detects even a weak reflected signal. Instead consider if this reflective sensor, which does not contain an AGC feature, is appropriate for your design.

Alternatively you might explore the response time of the AGC feature to see if you can defeat its intended purpose. That is to say, rapidly switch between IR transmitters in order to keep the AGC level at low gain. Essentially blinding it from weak reflected signals.

You might also transmit continuously on all IR sources and determine if the AGC will put the weak signals below the noise floor.
> 4 votes

# Answer
I realize this is old but I have had a similar challenge making an code wheel for an optical encoder. PLA material did not block the infrared. however, all of the codewheels that I have made with black PETG material have worked. Obviously you would want to fill in the shape as much as possible and assure that you do not have gaps between the layers. Personally I have not had to make any tweaks with the Prusa MK3 printer, black PETG material and the common 0.2 layer height.
> 3 votes

# Answer
The best and cheapest way would be to use BLACK colored printing material as it would absorb the IR waves and would not let them pass! I did a similar thing when I was building an IR-based Robot so using a black reflector and painting the chassis black increased the efficiency!

Black for visible light is the same for IR too as light is just a small spectrum of electromagnetic radiation, just as IR.
> 2 votes

---
Tags: ir
---


# Question
Title: Problem with L293D controlled motors using IR pilot remote
# I have a problem with my line follower:

My robot has 4 wheels with DC motors connected to L293D shield (Arduino Uno).

The robot is a line follower controlled by IR pilot with an IR receiver, it has 4 IR sensors(two in the back and two in the front). The robot goes forward if none of sensors sees the black line.

When I click \> button, the robot should use only the sensors in the front and follow the line until the end of the road made of black tape, and when I click \< it should use only the sensors on the back and run CarBackward() (go backwards).

The robot should only stop working if I click 0 button on the pilot (CarStop() function). So without the IR remote code the robot drives normally, but when I add the code for the pilot only two right motors work, they spin forward and nothing else happens no matter if one, two or none sensors see the line.

Everything is powered by two 18650 batteries.

The IR pilot receiver is connected to A0 pin on the shield - pin 14 (which can be used as digital).

```
#include <IRremote.h>
#include <AFMotor.h>

int IRsensorPin = 14;
AF_DCMotor motor1(1);
AF_DCMotor motor2(2);
AF_DCMotor motor3(3);
AF_DCMotor motor4(4);

IRrecv irrecv(IRsensorPin);
unsigned long key_value = 0;
decode_results results;

const int back_left_sensor_pin = A0;
const int left_sensor_pin = A1;
const int back_right_sensor_pin = A2;
const int right_sensor_pin = A3;
int left_sensor_state;
int back_left_sensor_state;
int right_sensor_state;
int back_right_sensor_state;

void CarBackward()
{
  if (back_left_sensor_state > 500 && back_right_sensor_state < 500)
  {
    Serial.println("turn right");
    motor1.run(BACKWARD); // LP
    motor2.run(RELEASE); // LT
    motor3.run(BACKWARD); // PT
    motor4.run(FORWARD); // PP

    motor1.setSpeed(160);
    motor2.setSpeed(130);
    motor4.setSpeed(180);
    delay(20);
  }

  if (back_left_sensor_state < 500 && back_right_sensor_state > 500)
  {
    Serial.println("turn left");
    motor1.run(FORWARD); // LP
    motor2.run(BACKWARD); // LT
    motor3.run(RELEASE); // PT
    motor4.run(BACKWARD); // PP

    motor1.setSpeed(180);
    motor4.setSpeed(160);
    motor3.setSpeed(130);
    delay(20);
  }

  if (back_left_sensor_state < 500 && back_right_sensor_state < 500)
  {
    Serial.println("forward");
    motor1.run(BACKWARD); // LP
    motor2.run(BACKWARD); // LT
    motor3.run(BACKWARD); // PT
    motor4.run(BACKWARD); // PP

    motor1.setSpeed(110);
    motor2.setSpeed(110);
    motor3.setSpeed(110);
    motor4.setSpeed(110);
    delay(20);
  }

  if (back_left_sensor_state > 500 && back_right_sensor_state > 500)
  {
    Serial.println("stop");
    motor1.setSpeed(0);
    motor2.setSpeed(0);
    motor3.setSpeed(0);
    motor4.setSpeed(0);
    delay(20);
  }
}

void CarForward()
{
  if (right_sensor_state > 500 && left_sensor_state < 500)
  {
    Serial.println("turn right");
    motor1.run(FORWARD); // LP
    motor2.run(FORWARD); // LT
    motor3.run(RELEASE); // PT
    motor4.run(BACKWARD); // PP

    motor1.setSpeed(160);
    motor2.setSpeed(130);
    motor4.setSpeed(180);
    delay(20);
  }

  if (right_sensor_state < 500 && left_sensor_state > 500)
  {
    Serial.println("turn left");
    motor1.run(BACKWARD); // LP
    motor2.run(RELEASE); // LT
    motor3.run(FORWARD); // PT
    motor4.run(FORWARD); // PP

    motor1.setSpeed(180);
    motor4.setSpeed(160);
    motor3.setSpeed(130);
    delay(20);
  }

  if (right_sensor_state < 500 && left_sensor_state < 500)
  {
    Serial.println("forward");
    motor1.run(FORWARD); // LP
    motor2.run(FORWARD); // LT
    motor3.run(FORWARD); // PT
    motor4.run(FORWARD); // PP

    motor1.setSpeed(110);
    motor2.setSpeed(110);
    motor3.setSpeed(110);
    motor4.setSpeed(110);
    delay(20);
  }

  if (right_sensor_state > 500 && left_sensor_state > 500)
  {
    Serial.println("stop");
    motor1.setSpeed(0);
    motor2.setSpeed(0);
    motor3.setSpeed(0);
    motor4.setSpeed(0);
    delay(20);
  }
}

void CarStop()
{
  Serial.println("stop");
  motor1.run(RELEASE);
  motor2.run(RELEASE);
  motor3.run(RELEASE);
  motor4.run(RELEASE);
  delay(200);
}

void setup()
{
  // put your setup code here, to run once:
  Serial.begin(9600);
  irrecv.enableIRIn();
  irrecv.blink13(true);
  motor1.setSpeed(130);
  motor2.setSpeed(130);
  motor3.setSpeed(130);
  motor4.setSpeed(130);
}

void loop()
{
  left_sensor_state = analogRead(left_sensor_pin);
  right_sensor_state = analogRead(right_sensor_pin);
  back_left_sensor_state = analogRead(back_left_sensor_pin);
  back_right_sensor_state = analogRead(back_right_sensor_pin);

  static int wariat_na_lini = 1;  // if = 1 follow the line and go forward, if -1 go backwards

  if (irrecv.decode(&results)) // have we received an IR signal?
  {
    if (results.value == 0xFFFFFFFF) // if the value is equal to 0xFFFFFFFF
    {
      results.value = key_value; // set the value to the key value
    }
    switch (results.value)
    {
      case 0xCBA816E1:
      case 0xC078:
        Serial.println("right button");
        wariat_na_lini = 1;
        break;
      case 0x43D69629:
      case 0xC0F8:
        Serial.println("left button");
        wariat_na_lini = -1;
        break;
      case 0xA6F5461D:
      case 0xC004:
        Serial.println("stop button");
        wariat_na_lini = 0;
        CarStop();
        break;
      default:
        Serial.println("different code");
        break;
    }
    key_value = results.value; // store the value as key_value
    irrecv.resume(); // reset the receiver for the next code
  }

  if (wariat_na_lini > 0) CarForward();
  else if (wariat_na_lini < 0) CarBackward();
}

```

So my question is - why are there only right motors working when the ir receiver is plugged?

This is my motor driver:

# Answer
> 0 votes
Your problem is most likely this line:

```
  irrecv.blink13(true);

```

That is intended to flash an LED on pin 13 when you use your IR remote. However pin 13 is also used by the motor shield as part of the serial protocol to communicate with the control chips.

By using that you are confusing the motor shield.

Just remove that line should allow the motors to work again.

---
Tags: arduino-uno, motor, ir, robotics
---


# Question
Title: Getting Accurate Velocity Readings From IMU
Hi I am currently using a BNO055 for a design project. This sensor outputs a linear acceleration vector corresponding to three (xyz) directions. I am trying to "integrate" the acceleration to get a speed the object it is mounted to is traveling. I noticed early on that in my speed graph there is large amounts of drift. I was looking for any guidance someone might have for tuning out the drift some way or filtering options I could use for acceleration data to reduce the drift

# Answer
> 2 votes
The process of integrating acceleration to derive velocity and integrating velocity to derive position are commonly known as dead reckoning. In this link it is stated:

> Dead reckoning is subject to cumulative errors. Advances in navigational aids that give accurate information on position, in particular satellite navigation using the Global Positioning System, have made simple dead reckoning by humans obsolete for most purposes.

It may help to calibrate each of the 3 accelerometers using Earth's gravity as a constant. Test if each accelerometer is symmetrical providing the same absolute values when pointed toward the Earth as when pointed away from the Earth. If any are not symmetric calculate an appropriate offset. Next compare the range of each of the 3 accelerometers. If they are not the same calculate an appropriate magnitude correction factor for maximum and minimum accelerometer ranges.

To find the offset and range correction values look at page 26 of the BNO055 specification sheet. There you will find a picture of the BNO055 chip which relates to the direction of the X, Y and Z accelerometers. Position the chip such that the X accelerometer is pointed downwards toward the earth. Record the raw value. Now repeat the measurement with the X accelerometer pointing away from the earth. The absolute value of these two measurements should be the same. If not, determine the offset needed to correct X accelerometer measurements and incorporate that value into your program. Repeat this for the Y and Z vectors.

Now compare the maximum - minimum values for the X, Y and Z accelerometers. These 3 values should be the same. If not, find a value to multiply the smallest of the three such that it matches the middle value and incorporate that value into your program. Repeat this for the largest of the three values.

It is desired all 3 accelerometers work the same. If they do not, using the values derived above should adjust the raw values such as the result appears as 3 nearly identical accelerometers.

That said, most accelerometers are very usable with no correction factors. And it is expected any correction factors to be small. However, as experienced, when integrating, small errors can accumulate quickly.

Next consider the application in which dead reckoning is to be used. There may be clues as to the velocity at a given moment which, if used, can reset the assumed velocity to a known value. For example, if the accelerometer were attached to a runner's foot, it can be assumed the velocity is zero for each foot to ground impact detected.

---
Tags: sensors, data, imu, bno055
---


# Question
Title: 'Serial1' was not declared in this scope for automatic plant watering
```
#include <LiquidCrystal.h>
#include <SoftwareSerial.h>
int in1 = 2;
int in2 = 3;
LiquidCrystal lcd(14,15,16,17,18,19);
int led = 13;
int flag = 0;
int motorpin = 11;
int sensorpin = 7;

void setup()
{
  lcd.begin(16,2);
  Serial1.begin(9600);
  pinMode(led, OUTPUT);
  pinMode(motor, OUTPUT);
  pinMode(sensor, INPUT_PULLUP);
  lcd.print("Plant Watering");
  lcd.setCursor(4,1);
  delay(2000);
  lcd.clear()
  lcd.print("RCC INSTITUTE");
  lcd.setCursor(0,1);
  lcd.print("Starting....");
  delay(2000);
  gsmInit();
  lcd.clear();
  lcd.print("System Ready");
}

void loop()
{
  lcd.setCursor(0,0);
  lcd.print("Automatic Mode");
  if (digitalRead(sensor) == 1 && flag == 0)
  {
    delay(1000);
    if (digitalRead(sensor) == 1)
    {
      digitalWrite(led, HIGH);
      sendSMS("Low Soil Moisture detected. Motor turned ON");
      lcd.begin(16, 2);
      lcd.setCursor(0, 1);
      lcd.print("Motor ON ");
      digitalWrite(motor, HIGH);
      delay(2000);
      flag=1;
    }
  } else if(digitalRead(sensor) == 0 && flag == 1)
  {
    delay(1000);
    if (digitalRead(sensor) == 0)
    {
      digitalWrite(led, LOW);
      sendSMS("Soil Moisture is Normal. Motor turned OFF");
      digitalWrite(motor, LOW);
      lcd.begin(16, 2);
      lcd.print("Motor OFF");
      lcd.setCursor(0, 1);
      lcd.print("Motor OFF");
      delay(2000);
      flag = 0;
    }
  }
}

void sendSMS(String msg)
{
  lcd.clear();
  lcd.print("Sending SMS");
  Serial1.println("AT+CMGF=1");
  delay(500);
  Serial1.print("AT+CMGS=");
  Serial1.print('"');
  Serial1.print("+918xxxxxxxxx"); // number
  Serial1.print('"');
  Serial1.println();
  delay(500);
  Serial1.println(msg);
  delay(500);
  Serial1.write(26);
  delay(1000);
  lcd.clear();
  lcd.print("SMS Sent");
  delay(1000);
  lcd.begin(16, 2);
}

void gsmInit()
{
  lcd.clear();
  lcd.print("Finding Module..");
  boolean at_flag = 1;
  while (at_flag)
  {
    Serial1.println("AT");
    while (Serial1.available() > 0)
    {
      if (Serial1.find("OK"))
      at_flag = 0;
    }
    delay(1000);
  }
  Serial1.println("ATE0"); //<=== it says 'Serial1' was not declared in this scope
  lcd.clear();
  lcd.print("Finding Network..");
  boolean net_flag = 1;
  while(net_flag)
  {
    Serial1.println("AT+CPIN?");
    while(Serial1.available() > 0)
    {
      if (Serial1.find("READY"))
        net_flag = 0;
      break;
    }
    delay(1000);
  }
  Serial1.println("AT+CNMI=2,2,0,0,0");
  delay(1000);
  Serial1.println("AT+CMGF=1");
  delay(1000);
  Serial1.println("AT+CSMP=17,167,0,0");
  lcd.clear();
  Serial1.flush();
}

```

# Answer
> 1 votes
The UNO only has one serial port, named `Serial`. You can create another one using SoftwareSerial (which you have included but not used) and you can, if you choose, name this `Serial1`.

```

#include <SoftwareSerial.h>

SoftwareSerial Serial1(4, 5); // RX, TX

```

---
Tags: arduino-uno
---


# Question
Title: Am I at the limit of UART transmission time?
I'm currently using an STM32F103C8 (With an arduino core) to read 4 sensors at 1kHz, then send that data via UART (at 115200 baud) to another device. Each sensor returns a float, I also include an unsigned long representing milliseconds since boot time. This adds up to be a 20 byte package, that I attempt to send at 1kHz. Sensor sampling is carried out via a timer interrupt, as it is crucial the time between samples is constant.

The data transmission itself (If I send it slowly) takes approx. 70 microseconds. When sped up to 1kHz, it takes approx. 2500. I assume this is because I am filling a serial buffer of some sort.

Is this about the limit of the communication method? If it takes longer than 1000 microseconds to send the data, then presumably the interrupt will trigger before the data is sent and it will have to start again?

# Answer
At 115200 baud you can send 11520 characters per second. At 20 bytes per packet you can send 576 packets per second. That's 1,736µs per packet.

That's assuming zero wait between bytes. That's not going to happen.

Your measurement of 70µs will just be the time taken to place data into the transmit buffer, and has nothing to do with how long the transmission itself takes.

Roll all that together and the value of 2,500µs per packet is not unreasonable.

To transmit faster you will simply have to run at a faster baud rate. If you're getting 2500µs per packet currently and a packet takes 1736µs (call it 1,750 for simplicity) then there's about a 750µs overhead per packet to do the actual work of sending the data from the buffer. I'll assume this is a fixed value, though with no knowledge of how the STM32F1 UART works it may not be.

If you want \<1000µs then that leaves you about 250µs of time to fit the packet into. That means an equivalent of 4,000 packets per second, or 80,000 bytes per second, or a baud rate of 800,000baud.

1 MBaud is more than possible, and is a good standard baud rate number that most things can cope with. So raising your baud rate to 1,000,000 *should* allow the communication to happen fast enough.
> 3 votes

# Answer
I tested a lot of baud rates on Arduino Unos, including cheap Chinese models, and decided to use a default 115200 for my DaqPort system (https://www.daqarta.com/dw\_rraa.htm). I had found problems, like the system hanging after a second or so at 150000 baud, and didn't want to have my users run into issues that would be hard to troubleshoot.

So I'm wondering if you can reduce the bytes you need to send. Do you really need to send floats? I'm thinking 4 bytes for the data and 4 for the time would give ample resolution for almost anything, and I can't (off the top of my head anyway) think of a sensor type with more than 32-bit resolution. Also, 32 bits of msec is nearly 50 days; if you need more than that it should be pretty easy to unwrap the times after the fact.

Just a thought...
> 0 votes

---
Tags: serial, uart, speed, stm32
---


# Question
Title: Standalone ATmega328P stops responding when RX is connected
I have followed this demo and have set up a standalone ATmega328P being programmed from a Raspberry Pi via the SPI lines. I have also added a 16 MHz crystal with 22 pF capacitors, as well as I have enabled and set up I²C between the ATmega and Raspberry Pi.

I have compiled and uploaded a bunch of programs and I can confirm everything works as expected.

As you can imagine, it is quite hard debugging things without a serial connection, so I connected pin 2 of the ATmega to GPIO14 of the Raspberry Pi and pin 3 to GPIO15. At this point, when I try uploading a program, I get this:

```
$ avrdude -P /dev/spidev0.0 -c linuxspi -p m328p -U flash:w:build-uno/program.hex

avrdude: error: AVR device not responding
avrdude: initialization failed, rc=-1
         Double check connections and try again, or use -F to override
         this check.

avrdude done.  Thank you.

```

If I break the pin2 to GPIO14 connection, then my program gets uploaded. And if I restore the connection between the pins and open Minicom on the Raspberry Pi I see the output of my simple program:

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

void loop() {
  delay(1000);

  Serial.println("Echo Test");
}

```

---

```
$ minicom -b 9600 -o -D /dev/ttyS0

Welcome to minicom 2.7.1

OPTIONS: I18n
Compiled on Aug 13 2017, 15:25:34.
Port /dev/ttyS0, 16:50:17

Press CTRL-A Z for help on special keys

Echo Test
Echo Test
Echo Test
Echo Test

```

But whenever I press a button on the keyboard (inside Minicom), I notice that the ATmega gets reset. If I hold the button down the transmission of "Echo Test" seizes as it is getting reset rapidly.

How can I get serial to function properly?

Addendum:

I'm using a Raspberry Pi 4, and in *raspi-config* I have disabled serial login and left the serial hardware enabled.

# Answer
> 4 votes
There are two things wrong with the circuit in that demo.

1. There is no decoupling capacitor on the power pins. This is required to keep the power stable during opertaion.
2. More critically: this is being powered from 3.3V, but is being run at 16MHz. That is outside specifications. You should use an 8MHz crystal to operate at 3.3V.

---
Tags: serial, atmega328, uart, reset
---


# Question
Title: How to override automatic control in Blynk app?
I am a beginner to Blynk, and have successfully built a simple water temperature control project. It consists of an ESP32, a plug-in water heater, and an AC relay board. The ESP32 controls the relay board, while the water heater is plugged into the relay board.

The code I have will turn on the relay once the water temperature dips below 16°C. On the Blynk app, I want to add a button that allows the user to manually control the operation of the relay. But I am stumped as to how to code it. Since I have programmed the ESP to turn off the relay once the temperature is above 16°C, if I try to switch it on manually at 20°C, for example, the relay will not remain on, because the `if` statement will fail.

How can I code this to have a manual override capability, so that once the user turns on the button inside the Blynk app, the ESP will allow manual control of the digital pin (delay trigger), and will only revert back to automatic temperature control mode once the button is turned off?

```
#include <WiFi.h>
#include <WiFiClient.h>
#include <BlynkSimpleEsp32.h>
#include <OneWire.h>
#include <DallasTemperature.h>

#define ONE_WIRE_BUS 14        //data wire connected to pin 14
#define RELAY_PIN 23           //IoT relay connected to pin 23

OneWire oneWire(ONE_WIRE_BUS); //instance to communicate with any OneWire device

DallasTemperature sensor(&oneWire); //pass reference to Dallas Temperature object

BlynkTimer timer;       //create Blynk timer object for timed intervals
float waterTemp;        //temperature from DS18B20 in C

char auth[] = "xxxxxxx";
char ssid[] = "xxxxxxx";
char pass[] = "xxxxxxx";

void setup() {
  Serial.begin(9600);
  sensor.begin();
  Blynk.begin(auth, ssid, pass);
  sensor.setResolution(9);           //default is 9 bit
  timer.setInterval(1000L, sendTemp);
  pinMode(RELAY_PIN, OUTPUT);
  digitalWrite(RELAY_PIN, LOW);
}

void sendTemp() {
  sensor.requestTemperatures();      //must request reading first
  waterTemp = sensor.getTempCByIndex(0);
  if (waterTemp != DEVICE_DISCONNECTED_C) {
    Serial.print("Temp = ");
    Serial.println(waterTemp);
    Blynk.virtualWrite(V1, waterTemp);
    if (waterTemp < 16) {
      digitalWrite(RELAY_PIN, HIGH); //turn on IoT relay
    } else {
      digitalWrite(RELAY_PIN, LOW);  //turn off IoT relay
    }
  } else {
    Serial.println("Error: Could not read temperature data");
    Blynk.notify("Error: Could not read temperature data");
    digitalWrite(RELAY_PIN, LOW);
  }
}

void loop(void) {
  Blynk.run();
  timer.run();
}

```

# Answer
> 1 votes
Roughly like this:

Make a global variable `int mode`;

Read a Blynk app 3-way switch in the `loop()`;

Set `mode` to the 1, 2, or 3 received from the Blynk app (for ON/OFF/AUTO);

Replace this bit of code:

```
if (waterTemp < 16) {
  digitalWrite(RELAY_PIN, HIGH); //turn on IoT relay
} else {
  digitalWrite(RELAY_PIN, LOW);  //turn off IoT relay
}

```

with

```
if (mode == 1) {
  digitalWrite(RELAY_PIN, HIGH);
} else if (mode = 2) {
  digitalWrite(RELAY_PIN, LOW);
} else {
  if (waterTemp < 16) {
    digitalWrite(RELAY_PIN, HIGH); //turn on IoT relay
  } else {
    digitalWrite(RELAY_PIN, LOW);  //turn off IoT relay
  }
}

```

You will still have to decide what happens when `DEVICE_DISCONNECTED_C == TRUE`, etc, but that is the gist of it.

---
Tags: esp32, code-review, blynk
---


# Question
Title: Is there a way to send a String via a Webserver Textbox without the use of the SD card?
Since my last post, I've been trying to do some extra things with my Stranger Things Wall Project.

I connected a LCD Screen (16x2) that will take any text being processed to the wall and show what is being written (So we can read the full message even if we lost the first chars being flashed)

The original example I followed used a Bluetooth App to send the message, however I want to use a Web Server with Ethernet.

My current challenge is if it is possible to make a WebServer to feed text to arduino, without the use of a SD card. I did manage to find an example that sends a simple command, but in my case, I need to call a function and sends a string.

My knowledge is limited on the areas of HTML and JS, so any help is welcome. If it matters, the Ethernet Shield I am using currently is the W5100.

The schematic is the same as the last post, however, here is the updated code:

```
#include <Wire.h> //INCLUSÃO DE BIBLIOTECA
#include <LiquidCrystal_I2C.h> //INCLUSÃO DE BIBLIOTECA
#include <SPI.h> //INCLUSÃO DE BIBLIOTECA
#include <Ethernet.h> //INCLUSÃO DE BIBLIOTECA

//Pin connected to ST_CP of 74HC595
#define latchPin 5
//Pin connected to SH_CP of 74HC595
#define clockPin 7
////Pin connected to DS of 74HC595
#define dataPin 6
// size of buffer used to capture HTTP requests
#define REQ_BUF_SZ   90
// size of buffer that stores a line of text for the LCD + null terminator
#define LCD_BUF_SZ   17
char HTTP_req[REQ_BUF_SZ] = {0}; // buffered HTTP request stored as null terminated string
char req_index = 0;              // index into HTTP_req buffer
LiquidCrystal_I2C lcd(0x27,16,2);
byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED }; //ATRIBUIÇÃO DE ENDEREÇO MAC AO ETHERNET SHIELD W5100 - ETIQUETINHA
EthernetServer server(80);
String text;                                                    //Variável do tipo string que receberá o texto

void setup() {
  Serial.begin(9600);                                           //Velocidade de comunicação
  for (int i = 2; i < 7; i++) {
    if (i != 4) {
      pinMode(i, OUTPUT);                                   //Declarando o pino como saída
    }
  }
  pinMode(8,OUTPUT);
  pinMode(9,OUTPUT);
  lcd.init();
  lcd.setBacklight(HIGH);
  lcd.setCursor(0,0);
  lcd.print("Iniciando");
  if (Ethernet.begin(mac) == 0) {
    lcd.clear();
    lcd.setCursor(1,0);
    lcd.print("FALHA AO PEGAR");
    lcd.setCursor(7,1);
    lcd.print("IP");
  // no point in carrying on, so do nothing forevermore:
    delay(5000);
    return;
  }
  // print your local IP address:
  lcd.clear();
  lcd.setCursor(0,0);
  lcd.print("PRONTO");
  lcd.setCursor(0,1);
  lcd.print(Ethernet.localIP());
  server.begin();
  brilho(255);
  inicializationEffect();                                       //Chamada da Função responsável pelo efeito inicial
}
void loop() {
   EthernetClient client = server.available();
  if (client) {
    Serial.println("new client");
    // an http request ends with a blank line
    boolean currentLineIsBlank = true;
    while (client.connected()) {
      if (client.available()) {
        char c = client.read();
        Serial.write(c);
        // if you've gotten to the end of the line (received a newline
        // character) and the line is blank, the http request has ended,
        // so you can send a reply
        if (c == '\n' && currentLineIsBlank) {
          // send a standard http response header
          client.println("HTTP/1.1 200 OK");
          client.println("Content-Type: text/html");
          client.println("Connection: close");  // the connection will be closed after completion of the response
          client.println("Refresh: 5");  // refresh the page automatically every 5 sec
          client.println();
          client.println("<!DOCTYPE HTML>");
          client.println("<html>");
          client.println("<h2>Stranger Things</h2><br />");
          client.println("</HTML>");
          break;
        }
        if (c == '\n') {
          // you're starting a new line
          currentLineIsBlank = true;
        } else if (c != '\r') {
          // you've gotten a character on the current line
          currentLineIsBlank = false;
        }
      }
    }
    // give the web browser time to receive the data
    delay(1);
    // close the connection:
    client.stop();
    Serial.println("client disconnected");
  }

  //receiveText();                                               //Chamada da função responsável por receber o texto digitado
}
//Função que recebe o texto diitado
void receiveText() {
  while (Serial.available() > 0) {                              //Verifica se existe alguma informação na Serial
    char c = Serial.read();                                     //atribui cada caractere a variável c que é do tipo char
    if (c != '\n') text.concat(c) ;                              //verifica se a variável do tipo char recebeu uma quebra de linha que indica o fim da palavra ou frase e concatena todos os caracteres na String text
    delay(10);                                                  //aguarda 10 milissegundos
  }
  if (text.length() > 0) {                                      //verifica se a string text tem tamanho maior que 0
    text.toUpperCase();                                       //transforma tudo que estiver na string text para maiúsculo
    if (text[0]=='#'){
      waveEffect();
    }else if(text[0]=='!'){
      blink();
    }else {
      executeEffect(text);                                        //chama a função executeEffect passando a string text como parâmetro
    }
  }
  text = "";                                                    //limpa a string text
}
//Função responsável por ativar linha que recebe como parâmetro o número da linha
void lineActivation(int line, int keepalive) {
  if (keepalive == 0) {
    for (int i = 2; i <= 4; i++) {
      if (i == 4) { i = 8; } //porta 4 usada pelo SD do Ethernet
      digitalWrite(i, LOW);
    }
  }
  if (line >= 1 && line <=3){
    if (line == 3) { line = 7; } //porta 4 usada pelo SD do Ethernet
    digitalWrite(line+1, HIGH);                               //coloca a linha 1 em estado lógico alto
  }
}

void activateLetter(char letter, int on, int off) {
  int lt;
  brilho(255);
  lt = (((int)letter - 64) % 9);
  if (((int)letter - 64) > 8) {
    lt = lt + 1;
  }
  if (on) {
    callCol(1<<lt-1);
    delay(on);                                                //mantém o pino em nível lógico alto durante o tempo que foi determinado no parâmetro da função
  }
  if (off) {
    callCol(0);
    delay(off);                                               //mantém o pino em nível lógico baixo durante o tempo que foi determinado no parâmetro da função
  }

}

void callCol(int col){
  digitalWrite(latchPin, LOW);
shiftOut(dataPin, clockPin, MSBFIRST, highByte(col));
shiftOut(dataPin, clockPin, MSBFIRST, lowByte(col));
  digitalWrite(latchPin, HIGH);

}
void executeEffect(String text) {
  for (int i = 0; i < text.length(); i++) {
    if (text[i] == ' ') {
      delay(1000);
    } else if ((int)text[i] < 65 or (int)text[i] > 90) {
    } else {
      lineActivation(int(((int)text[i] - 64) / 9) + 1, 0);
      activateLetter(text[i], 1000, 200);
    }
  }
}

void inicializationEffect() {
  for (int i = 1; i < 27; i++) {
    lineActivation(int(i / 9) + 1, 0);                          //ativa a linha
    activateLetter(char(64 + i), 100, 10);                   //ativa a letra
  }
}
void waveEffect() {
  Serial.println("Wave");
  for (int i = 1; i < 4; i++) {
    lineActivation(i, 1);                          //ativa a linha
  }
  for (int i = 1; i < 10; i++) {
    activateLetter(char(72 + i), 100, 0);
  }

  for (int i = 1; i < 10; i++) {
    activateLetter(char(72 + i), 0, 100);
  }
    lineActivation(0, 0);                          //ativa a linha

}
void blink() {
  Serial.println("Blink");
  callCol(511);
  lineActivation(1,1);
  lineActivation(2,1);
  lineActivation(3,1);
  for (int i = 0; i < 256; i++){
    brilho(i);
    delay(1);
  }
  delay(100);
  for (int i = 255; i >= 0; i--){
    brilho(i);
    delay(1);
  }
}

void brilho(byte brt) { // 0 to 255
  analogWrite(9, 255-brt);
}

```

# Answer
> 2 votes
Yes, and it's not too hard, but do you do need to do string parsing in C to achieve it.

In your code you read the header of the HTTP request byte by byte and send it to serial, essentially discarding it.

Instead you need to read the header line by line (at least the first line) and parse the URL parameters.

The format of the first line should be something like:

```
GET / HTTP/1.1

```

or:

```
GET /?text=This+will+be+displayed HTTP/1.1

```

You need to parse that to get everything between `=` and the the space if they exist. You can then display it as you wish.

Next you also need to alter the code that is sending the web page content to also include a simple HTML form with the GET method and the destination of `/`, which contains a text field called `text`.

---
Tags: arduino-uno, web-server, ethernet-shield
---


# Question
Title: Can ESP 32 use the wire library exactly like that was in Arduino?
Compare the YouTube video and this webpage, the former one made programming very different in ESP32 and that was in Arduino nano, while the webpage seemed to imply that they work exactly the same.

Can we use the same code for standard Arduino library, like wire library, for ESP32 and ESP8266, or do we have to do something different?

# Answer
> 5 votes
Code using the Arduino Wire library is generally portable between processors, but there are pitfalls to watch for. One that I'm aware of is a difference in the Wire libraries for the ESP32 and ESP8266. The TwoWire::begin() method for the ESP32 has prototype:

```
bool TwoWire::begin(int sdaPin, int sclPin, uint32_t frequency);

```

whereas for the ESP8266 it is:

```
void TwoWire::begin(int sda, int scl, uint8_t address);

```

So, a call to begin() using the ESP#2 library will set the clock using the third parameter, whereas on the ESP8266 it will truncate the third parameter and use it as an address.

If you wish code to be portable between the ESP32 and ESP8266, then the fix for this particular issue is to call `TwoWire::begin( my_SDA_pin, my_SCL_pin )` (specifying only two parameters:the SDA and SCL pins), and use a separate call to `TwoWire::setClock( my_clock_speed )` to set the clock.

There may be other differences I'm not aware of...

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


title: Form a signal from an array of bits

text:
# Question
Title: Form a signal from an array of bits
I need to reproduce with a digital pin of an Arduino such a key in the form of a sequence of 1's and 0's, where a one takes 2 ms high and 2 ms low, and a zero takes 1 ms high and 1 ms low.

```
  int key = 0b101100001111;

void setup()
{
  pinMode(13, OUTPUT);
}

void loop()
{
  for (int n = 0; n < 12; n++)
  {
    if (bitRead(key, n) == 1) //execute if bit value == 1
    {
      sendSignal(2000);
    }

    else //execute if bit value == 0
    {
      sendSignal(1000);
    }
  }
}

void sendSignal(int duration)
{
  digitalWrite(13, HIGH);
  delayMicroseconds(duration);
  digitalWrite(13, LOW);
  delayMicroseconds(duration);
}

```

This sketch really works! I figured out what my problem is: I actually need a longer key (64 bits). I am using long type: long key = 0b1000011110001101111100011111001010110001101101111011011100110100; but long only allows 32 bits. What do you recommend to do? Maybe you need to arrange it as an array? I think you can make it easier somehow. thank you

# Answer
> 2 votes
You should make

```
byte key = 0b101100001111;

```

global, i.e. put it BEFORE the `setup` function and not within it.

Also, a byte only can contain 8 bits, you need 12, so make it an int (thanks to ocrdu, see comment below):

```
int key = 0b101100001111;

```

If you need more bits, you can use uint32\_t or uint64\_t, and count further than the current 12.

Now `key` is a local variable which is removed after exiting the `setup` function.

I'm not sure where 'key' comes from in:

```
switch (bitRead(key, n)) {

```

Do you get a compiler error, or did you ALSO define a global variable named `key` ? Anyway, if you make `key` global it will fix either way.

A few other remarks:

* Try to align your parenthesis, like the 3 }'s at the end, indent them properly, this makes your code much more readable
* Instead of the `switch`/`case`, you could use an `if` statement in this case, as the re are only (and always) two possible values (0 and 1):

Thus:

```
 if(bitRead(key, n) == 0)
 {
     ...
 }
 else // 1
 {
     ...
 }

```
* Try also comments to write in English instead of Greek, you never know when your comments will be read by non Greek readers (like now).
* You can make the following fragment shorter and less duplicated:

Original:

```
digitalWrite(13, HIGH);
delayMicroseconds(1000);
digitalWrite(13, LOW);
delayMicroseconds(1000);

```

If you wrap this in a function:

```
void sendSignal(int duration)
{
    digitalWrite(13, HIGH);
    delayMicroseconds(duration);
    digitalWrite(13, LOW);
    delayMicroseconds(duration);
}

```

Then you can write a 1 by calling:

```
sendSignal(2000);

```

and a 0 by calling:

```
sendSignal(1000);

```

# Answer
> 2 votes
If you modify the code slightly, you can use an array of characters of any length, so need to worry about digital word length.

Here's a modified version of your program that does this.

Note that I also took the liberty of replacing the 'magic number' 13 with LED\_PIN, and the 'magic number' 12 with KEY\_LEN. I would suggest you do the same with your pulsewidth values - maybe something like PULSE\_WIDTH\_ONE\_USEC and PULSE\_WIDTH\_ZERO\_USEC? That way someone else (or you 3 months later) looking at your code can easily see what the values are intended to do

```
const int KEY_LEN = 62;
const char key[KEY_LEN] = { "10110110110101111001011010110100101011011100110110101101101100" };
const int LED_PIN = 13;

//int key = 0b101100001111;
void setup()
{
  Serial.begin(115200);
  pinMode(13, OUTPUT);
}

void loop()
{
  for (int n = 0; n < KEY_LEN; n++)
  {
    if (key[n]== '1') //execute if bit value == 1
    {
      Serial.print("1");
      sendSignal(200);
    }

    else if (key[n] == '0')//execute if bit value == 0
    {
      Serial.print("0");
      sendSignal(100);
    }
    else
    {
      Serial.print("x");
    }
  }
  Serial.println();
}

void sendSignal(int duration)
{
  digitalWrite(LED_PIN, HIGH);
  //delayMicroseconds(duration);
  delay(duration);
  digitalWrite(LED_PIN, LOW);
  //delayMicroseconds(duration);
  delay(duration);
}

```

---
Tags: programming, arduino-ide, array, bit
---


title: Programming an AVR using ISP

text:
# Question
Title: Programming an AVR using ISP
I am trying to program an atmega with arduino sketch using ISP only (mac user). So I know how to burn a boot loader, and then to program the chip using the TX, RX. But I would like to program it directly using ISP, without a boot loader. So I am using the UNO as a ISP programmer, and trying without success to program a chip on a PCB:

1. I upload to the UNO the ArduinoISP sketch
2. Connect the lines to the target board (target board have atmega328, crystal, capacitors, LED)
3. Choose the board "Arduino pro or pro mini" in the Arduino IDE.
4. Choose the programmer- "Arduino as ISP"
5. At the beginning I tried to upload a boot loader, to see if its going well, it DID boot loaded the chip,so I know the connections are good, and I am set to go.

**Now, I am trying to just upload a sketch using the SAME ISP connection, I didn't touch anything(!)** , so I opened the blinking example, hit the upload button, and it's just not working (not in sync).

Again, the goal is now to program a chip with ISP directly, without a boot loader. The reason I boot loaded it is to see it's all connected well.

I can't imagine how the exact same configuration can bootload the chip,and later can't upload a sketch directly using the ISP.

What am I missing here? Can't you use the Arduino IDE to upload a sketch directly as an ISP programmer?

# Answer
You probably used a direct upload button that uses default Arduino programming using RX TX, not the programmer you had selected.

All wirings are perfect that's why you were able to burn the bootloader.

Now you just need to go under **Sketch -\> Upload Using Programmer.**
> 1 votes

---
Tags: avr, isp
---


# Question
Title: How to use the pushbutton without using if, else
I want to let the led blink for 3 seconds then 2 seconds then one second using the button one time and without using if/else

```
void setup() {
    // put your setup code here, to run once:
    pinMode(5, INPUT);
    pinMode(6, OUTPUT);
}

void loop() {
    // put your main code here, to run repeatedly:
    digitalRead(5, HIGH);
    digitalWrite(6, HIGH);
    delay(3000);
    digitalWrite(6, LOW);
    digitalWrite(6, HIGH);
    delay(2000);
    digitalWrite(6, LOW);
    digitalWrite(6, HIGH);
    delay(1000);
}

```

# Answer
As the required operation is finite and short, you can just hard code the sequence.
> 1 votes

# Answer
You could you simple inversion of boolean variable to set state of LED.

```
const int LedPin = 5;
bool ledState = true;

// in your loop

// bool will be transformed from true to 1 (HIGH)
digitalWrite(LedPin, (int)ledState);
// invert LED state to be false
ledState = !ledState;
// false -> 0 (LOW)
digitalWrite(LedPin, (int)ledState);

```
> 1 votes

# Answer
Ternary operator maybe helpful. \[Reference\]
> 1 votes

---
Tags: arduino-uno
---


title: MQ7 Readings are too high

text:
# Question
Title: MQ7 Readings are too high
I am currently trying to learn how to use my MQ 7 CO Standalone to read CO in the air around the sensor. Currently Im using this circuit using my Arduino Uno. I get results of 900-1000. Here's a Fritzing Schematic on my setup.

Currently this is the code I am using on the arduino:

\[code\]

```
int mqx_analogPin = A0; // connected to the output pin of MQ-X

void setup(){
  Serial.begin(9600); // open serial at 9600 bps
}

void loop()
{
  // give ample warmup time for readings to stabilize

  int mqx_value = analogRead(mqx_analogPin);
  Serial.println(mqx_value);

  delay(100); //Just here to slow down the output.
}

```

I'm following the setup from this Instructables: http://www.instructables.com/id/Smoke-Detector/?ALLSTEPS

However his readings are around 150-200ppm outside. I'm unsure how to reach these values since im following basically everything from the guide. Does anyone any experience with a MQ7 sensor?

I've been reading I need to preheat the sensor but I can't find any circuit that clearly shows how to preheat an MQ7 sensor or find any code for the arduino.

# Answer
Using of this sensor is a bit more complicated than that. You must cycle through 60 seconds of heating and 90 seconds of measurement cycles, during heating you need to provide 5V on its heater pins, during measurement you need to provide 1.4V, so you'll need transistor or some other PWM-controlled current limiter (Arduino pin can't provide enough current for sensor heating). I've tried to explain all details and calibration process here: https://www.instructables.com/id/Arduino-CO-Monitor-Using-MQ-7-Sensor/
> 3 votes

# Answer
Yes, it is not easy, lot of details to MQ-7 is here: http://www.arduinohobby.euweb.cz/ in the section "Analysator CO"
> 1 votes

---
Tags: serial
---


# Question
Title: Arduino Esp8266 Signal(TIMER0_COMPA_vect) can’t compile
Trying to compile a program containing the statement SIGNAL(TIMER0\_COMPA\_vect) written for arduino. But I want to use it on an esp8266 board. The code will compile for Arduino uno. But I get an error “expected constructor, destructor, or type conversion before ‘(‘ token when I try to compile for a Wemos D1 board. Can anyone help me convert the statement to pass the compile test. Thank you

# Answer
That instruction is for setting up an interrupt handler for the timer. It is very much specific to the AVR.

There's a lot more to do that just adjust that one statememt - you have to completely rewrite the whole of the timer code that you're using to operate with the ESP8266 SDK calls.

Without knowing what your code intends to achieve it's impossible to help you further, but this library may be of help to you.
> 3 votes

---
Tags: esp8266
---


# Question
Title: Arduino TFMini Lidar sensors and speaker
I have this code for the TFMini Lidar sensors and Speaker. I Need help figuring why I'm using this calculation in my code and why if I removed it the lidar will not give me any measurement? (see below plz).

And my code now it's only one sensor is working pins (4,5) I don't know why the three of them don't work together. Thanks in advance.

I took this code from the internet My coding experience is basic .

```
rx[i] = TFMiniOne.read();
if (rx[0] != 0x59) {
  i = 0;
} else if (i == 1 && rx[1] != 0x59) {
  i = 0;
} else if (i == 8) {
  for (j = 0; j < 8; j++) {
    checksum += rx[j];
  }
  if (rx[8] == (checksum % 256)) {
    *distance = rx[2] + rx[3] * 256;
    *strength = rx[4] + rx[5] * 256;
  }
  i = 0;
} else {
  i++;
}

```

Here is the complete code:

```
#include "Talkie.h"
#include "Vocab_US_Large.h"
#include <SoftwareSerial.h>
#include "TFMini.h"
TFMini tfminiOne;
TFMini tfminiTwo;
TFMini tfminiThree;

Talkie voice;
const int Speaker = 3;

//Declaring variables and constants

SoftwareSerial TFMiniOne (4,5);    //(RX, TX)
SoftwareSerial TFMiniTwo (6,7);
SoftwareSerial TFMiniThree (8,9);

void getTFminiData(int* distance, int* strength) {
  static char i = 0;
  char j = 0;
  int checksum = 0;
  static int rx[9];
  if (TFMiniOne.available()) {
    // Serial.println( "tfmini serial available" );
    rx[i] = TFMiniOne.read();
    if (rx[0] != 0x59) {
      i = 0;
    } else if (i == 1 && rx[1] != 0x59) {
      i = 0;
    } else if (i == 8) {
      for (j = 0; j < 8; j++) {
        checksum += rx[j];
      }
      if (rx[8] == (checksum % 256)) {
        *distance = rx[2] + rx[3] * 256;
        *strength = rx[4] + rx[5] * 256;
      }
      i = 0;
    } else {
      i++;
    }
  }
}

void setup() {
  pinMode(Speaker, OUTPUT);

  //Initializing
  Serial.begin (115200);
  while(!Serial);                     //Wait for USB Serial Port to connect
  Serial.println("Initializing...");
  TFMiniOne.begin (TFMINI_BAUDRATE);

  //Initializing TFMini Sensors
  tfminiOne.begin(&TFMiniOne);
  tfminiTwo.begin(&TFMiniTwo);
}

void loop() {
  int distance = 0;
  int strength = 0;

  getTFminiData(&distance, &strength);
  while (!distance) {
    getTFminiData(&distance, &strength);
    if (distance) {
      Serial.print(distance);
      Serial.print("cm\t");
      Serial.print("strength: ");
      Serial.println(strength);
    }
  }

  delay(100);

  if (distance > 30) {
    digitalWrite(Speaker,HIGH);
    voice.say(sp2_ALERT);
    voice.say(sp2_F);
  } else {
    digitalWrite(Speaker,LOW);
  }

  if (distance > 20) {
    digitalWrite(Speaker,HIGH);
    voice.say(sp2_ALERT);
    voice.say(sp2_L);
  } else {
    digitalWrite(Speaker,LOW);
  }

  if (distance < 15) {
    digitalWrite(Speaker,HIGH);
    voice.say(sp2_ALERT);
    voice.say(sp2_R);
  } else {
    digitalWrite(Speaker,LOW);
  }
  delay(300);

```

# Answer
> 0 votes
I can't answer the first part of your question as I don't understand what you're asking. However:

> I don't know why the three of them don't work together.

That doesn't work for 2 reasons:

1. Your receiving routine specifically references only one TFMini serial port, and
2. It is impossible to receive from more than one SoftwareSerial port at a time.

If you want to use multiple units you really should choose a microcontroller that has enough hardware UARTs to do the job. The Uno is not a suitable board.

Try the Mega2560 or one of the myriad of 32-bit ARM or MIPS boards.

# Answer
> 0 votes
> I don't know why the three of them don't work together.

I already answered that question in my answer to your previous question.

> why I'm using this calculation in my code and why if I removed it the lidar will not give me any measurement?

That code part is reading the data from the first `SoftwareSerial` interface. If you don't read this data (by removing this code part) you are not reading any data from the TFMini, thus you don't have any measurement. If you want measurements from the lidar sensor, don't remove the code part, that actually reads the measurements.

Besides that I will explain the complete function here in comments to the code. Before that, you should understand what the `static` keyword means here. Normal variables, that get declared inside a function, (aka local variables) will get destroyed, when the code reaches the end of the function. Variables marked with the keyword `static` will continue to exist and hold their value also after the function ended. They act a lot like global variables, though their namespace is local to the function (thus you can declare other variables with that name in other parts of your code).

```
void getTFminiData(int* distance, int* strength) {
  static char i = 0; // this counter variable denotes the position of the next to be received byte in the buffer rx.
  char j = 0; // temporary counter variable
  int checksum = 0; // will be used to calculate the checksum, so that it can be compared to the one send with the data
  static int rx[9]; // this is the receive buffer, where the received data will be put

  if (TFMiniOne.available()) { // When data is available on the serial interface, read one byte
    // Serial.println( "tfmini serial available" );
    // read one byte into the current position in the buffer
    rx[i] = TFMiniOne.read();

    // A valid message starts with two bytes of the value 0x59, so we restart, if the current message doesn't have that. (checking the first two bytes with these two if statements)
    if (rx[0] != 0x59) {
      i = 0;
    } else if (i == 1 && rx[1] != 0x59) {
      i = 0;
    } else if (i == 8) { // if we received 9 bytes (positions 0 to 8 in the buffer), the message is complete --> process it

      // Calculating the checksum by adding all bytes together
      for (j = 0; j < 8; j++) {
        checksum += rx[j];
      }

      // Comparing the calculated checksum with the last byte, that was received, (which is the checksum)
      // as the checksum is only one byte, we calculate the modulo with 256, thus only leaving the number range 0-255.
      if (rx[8] == (checksum % 256)) {
        // The checksums are equal, so the data is valid and we can proceed
        // The values for distance and strength have two bytes. Thus we need to put these bytes together into one value.
        *distance = rx[2] + rx[3] * 256;
        *strength = rx[4] + rx[5] * 256;
      }

      // reset the counter, since we have a full message and can now receive the next message
      i = 0;
    } else {
      // increment the counter variable to the next position, if we are currently receiving the bytes of a valid message
      i++;
    }
  }
}

```

I hope this makes the code clearer. As already said the my previous answer, it doesn't make much sense, to first use the TFMini library (declaring the corresponding objects) and then doing the communication yourself. I would suggest, that you look closer into the TFMini library. Try the examples, that surely come with the library. Use the libraries functions to communicate with the sensors. That will make it way easier for you, since the library will do the communications for you.

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


# Question
Title: No programmers available for this board - Programming ESP32 Cam with Ardunio IDE
This is my first time working with ESP32 Cam boards. I have followed the instructions as given in this site https://technoreview85.com/how-to-program-esp-32-cam-using-arduino-uno-board/ However my IDE doesn't display any programmers for this board.

Couldn't find any details about this in google. I just want to know how I could fix this problem(i.e. get the programmers listed). Thanks in advance.

# Answer
There are no programmers for ESP32. It only accepts Serial upload over bootloader.

Versions of IDE before 1.8.13 displayed programmers for all board support packages, that is why a programmer could be selected. Now only programmers for package of the selected board are available. But programmers are used only with the "Burn bootloader" or "Upload with programmer" commands, not with standard Serial upload over bootloader.
> 6 votes

# Answer
The older version of Arduino IDE. 1.8.12 worked.
> 3 votes

---
Tags: arduino-ide, esp32, programmer, camera
---


# Question
Title: Arduino waits until button release to activate
I'm fairly new to arduino, and on my own I'm trying to move a servo to the left and right using 2 buttons. I've got it working for the most part, however when I hold the button down nothing happens, and when I finally release the servo moves a certain amount based on how long I was holding the button down. I would like the servo to move when the button is being held down though. The servo also occasionally moves oddly and sporadically. I'm thinking its most likely a logic error in the code, but I can't figure it out. Could someone please tell me what they think I've done wrong? Thank you.

code:

```
#include <Servo.h>
Servo servo;

#define right 9
#define left 8

int angle = 90;
int angStep = 5;

void setup() {
  // put your setup code here, to run once:
  Serial.begin(9600);
  pinMode(right, INPUT_PULLUP);
  pinMode(left, INPUT_PULLUP);
  servo.attach(2);
  servo.write(angle);
  Serial.print("Begin");
  Serial.print('\n');
  Serial.print(angle);
  Serial.print(angle);
}

void loop() {
  // put your main code here, to run repeatedly:
  if (digitalRead(left) == HIGH && angle < 180){
    angle += angStep;
    Serial.print(angle);
    Serial.print('\n');
    servo.write(angle);
    delay(50);
  }

  if (digitalRead(right) == HIGH && angle > 0){
    angle -= angStep;
    Serial.print(angle);
    Serial.print('\n');
    servo.write(angle);
    delay(50);
  }
}

```

# Answer
I think it's because you are using a pullup resistor, so it's constantly HIGH instead of constantly LOW. Try changing HIGH and LOW to the opposite.
> 2 votes

---
Tags: arduino-uno, arduino-ide, servo, c, button
---


title: How to make my LCD screen brighter

text:
# Question
Title: How to make my LCD screen brighter
I'm trying to make my LCD screen brighter, can someone can help?

These are the code and the connections:

```
//LCD
#include <LiquidCrystal.h>
int Contrast=75;
LiquidCrystal lcd(12, 11, 5, 4, 3, 2);

//LED
int LdrPin = A0;   // the cell and 10K pulldown are connected to a0
int LdrValue = 0;  // the analog reading from the sensor divider
int LedPin = 10;   // connect Red LED to pin 11 (PWM pin)
int LedBrightness;

//כתום
int LdrPin2 = A0;  // the cell and 10K pulldown are connected to a0
int LdrValue2 = 0; // the analog reading from the sensor divider
int LedPin2 = 9;   // connect Red LED to pin 11 (PWM pin)
int LedBrightness2;

//צהוב
int LdrPin3 = A0;  // the cell and 10K pulldown are connected to a0
int LdrValue3 = 0; // the analog reading from the sensor divider
int LedPin3 = 8;   // connect Red LED to pin 11 (PWM pin)
int LedBrightness3;

//serial monitor
char rx_byte = 0;
//random
long randNumber;

void setup()
{
  //אתחול LCD
  analogWrite(6, Contrast);
  lcd.begin(16, 2);

  //אתחול LED
  pinMode(LdrPin, INPUT);
  pinMode(LedPin, OUTPUT);
  Serial.begin(9600);

  pinMode(LdrPin2, INPUT);
  pinMode(LedPin2, OUTPUT);
  Serial.begin(9600);

  pinMode(LdrPin3, INPUT);
  pinMode(LedPin3, OUTPUT);
  Serial.begin(9600);

  //serial monitor
  Serial.begin(9600);

  //random אתחול
  Serial.begin(9600);
  randomSeed(analogRead(0));
}

void loop()
{
  // lcd.setCursor(2, 0);
  // lcd.print("Good Morning");

  LdrValue = analogRead(LdrPin);
  //Serial.print("LDR reading = ");
  //Serial.println(LdrValue);    // print the raw analog reading
  LedBrightness = map(LdrValue, 679, 6, 255, 0);

  if (Serial.available() > 0) // is a character available?
  {
    rx_byte = Serial.read();       // get the character
  }
  //check if morning and show good morning on thr LCD
  if (LdrValue == 679 && rx_byte == '7')
  {
    lcd.setCursor(2, 0);
    lcd.print("Good Morning!");
    //random 50% order of lights
    randNumber = random(0, 2);
    Serial.print(randNumber);
    if (randNumber == 1)
    {
      //אדום
      for (int i=0; i<8; i++)
      {
        digitalWrite(LedPin, HIGH);
        delay(1000);
        digitalWrite(LedPin, LOW);
        delay(1000);
        //led start working on red
        lcd.setCursor(2, 0);
        lcd.print("working on");
        lcd.setCursor(2, 1);
        lcd.print("red");
      }
      //כתום
      for (int i=0; i<4; i++)
      {
        digitalWrite(LedPin2, HIGH);
        delay(1000);
        digitalWrite(LedPin2, LOW);
        delay(1000);
        //led start working on orange
        lcd.setCursor(2, 0);
        lcd.print("working on");
        lcd.setCursor(2, 1);
        lcd.print("orange");
      }

      //צהוב
      for (int i=0; i<5; i++)
      {
        digitalWrite(LedPin3, HIGH);
        delay(1000);
        digitalWrite(LedPin3, LOW);
        delay(1000);
        //led start working on yellow
        lcd.setCursor(2, 0);
        lcd.print("working on");
        lcd.setCursor(2, 1);
        lcd.print("yellow");
      }
    } else
    {
      //צהוב
      for (int i=0; i<5; i++)
      {
        digitalWrite(LedPin3, HIGH);
        delay(1000);
        digitalWrite(LedPin3, LOW);
        delay(1000);
        //led start working on yellow
        lcd.setCursor(2, 0);
        lcd.print("working on");
        lcd.setCursor(2, 1);
        lcd.print("yellow");
      }

      //כתום
      for (int i=0; i<4; i++)
      {
        digitalWrite(LedPin2, HIGH);
        delay(1000);
        digitalWrite(LedPin2, LOW);
        delay(1000);
        //led start working on orange
        lcd.setCursor(2, 0);
        lcd.print("working on");
        lcd.setCursor(2, 1);
        lcd.print("orange");
      }

      //אדום
      for (int i=0; i<8; i++)
      {
        digitalWrite(LedPin, HIGH);
        delay(1000);
        digitalWrite(LedPin, LOW);
        delay(1000);
        //led start working on red
        lcd.setCursor(2, 0);
        lcd.print("working on");
        lcd.setCursor(2, 1);
        lcd.print("red");
      }
    }
  } else
  {
    lcd.setCursor(2, 0);
    lcd.print("Good night!");
  }
}

```

# Answer
> 1 votes
For a complete answer, we would need the datasheet of the LCD screen, but in general, LCD screens have a pin for the backlight, or two, one for plus and one for ground.

In the datasheet you can find what voltage the backlight wants, and what the maximum voltage is, and then set it to what you want.

For extra points, you can feed the backlight with PWM and set the brightness from the Arduino; if you do, make sure you don't pull too much current from the Arduino pin; add a FET if necessary.

# Answer
> 1 votes
Use a 220 ohm resistor for the backlight. Treat it just as an LED. That's what it is, just a normal LED.

---
Tags: arduino-uno, lcd
---


# Question
Title: Serial.print skips or hangs inside a "if" statement. Trying to call a function VIA serial uart
I have two microcontrollers talking to each other using serial UART pins.

Now for some reason which I can not figure out why... doing a `Serial.print()` does not work in an "if" statement. And also assigning/declaring/initializing variables and values inside the "if" statement does not work... this is really weird. I can turn on the GPIO pins in the "if" statement but other than that nothing else works.

Microcontrollers are: Arduino Nano and WeMos D1 Mini.

Just want to note that both of the microcontrollers are talking to each other fine and arduino can determine the serial input but it can not "Serial.print" in the "if" statement of "strcmp", it is being skipped.

EDIT: I just woke up this morning, and magically "Serial.print" is working properly inside the "if" statement of "strcmp"... I guess the microcontroller needed some rest, I was testing it for 13+ hours...

Please view the code below:

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

    void loop()
    {
      char a[5];
      delay(100);
      int i = 0;

      if (Serial.available() > 0)
      {
        while(Serial.available() > 0)
        {
            a[i]=Serial.read();
            i++;
        }

        a[i] = '\0';  //last character inserted with a "null char".
      }

     if(strcmp(a,"RGB_1") == 0)   //<----- "if" statement, comparing the string array buffer
     {
        int m = 1; //<---------------- declaring and initializing a variable
        //Serial.print(m); //<-------- Serial monitor will hang and skip the GPIO pins below to trigger.
        digitalWrite(12, HIGH);
        delay(1000);
        Serial.print(m); //<---------- "if" statement allows the GPIO pins to trigger but skips this serial print.
     }
   }

```

# Answer
> 5 votes
High likely you are exceeding your character array, see:

```
char a[5];

```

Which can hold 5 characters. However, you write:

```
if(strcmp(a,"RGB_1") == 0)

```

Which assumes you receive "RGB\_1" which is 6 characters, because a string ends with a 0.

What also might happen is that you indeed receive only 5 characters without the ending newline, which means strcmp keeps searching until it finds a string end which may not happen.

So you can increase the array size a few just for testing purposes, and print `i` as jsotola proposes. Beyond that, also print each character you put into the array so you know how/if to handle a new line.

If you don't receive a string end, then use instead of the `strcmp` function, then use `strncmp`, which can search for exactly 5 characters, not checking until the end of the string.

---
Tags: serial, arduino-nano, uart, functions
---


# Question
Title: How to include a file from another (parent) directory
This is my structure

```
program/
  src/
    Makefile
    main.ino
    test.h
    ...
  lib/
    i2c.h

```

In `main.ino` I include `test.h` and in `test.h` I'm trying to include `i2c.h` but it is just not working, I keep getting:

```
make: *** No rule to make target 'i2c.h', needed by 'build-uno/main.ino.o'.  Stop.

```

I tried including like this

```
// test.h
#include "../lib/i2c.h"

```

I also tried making a symlink to my lib folder in arduino libraries and adding it as a library in Makefile

`sudo ln -s /home/pi/program/lib /usr/share/arduino/libraries/GAVR`

```
# Makefile
ARDUINO_DIR = /usr/share/arduino
BOARD_TAG = uno
ARDUINO_PORT = /dev/ttyAMA0
ARDUINO_LIBS = GAVR
include /usr/share/arduino/Arduino.mk

```

I also tried making a symlink to lib inside the src directory

`ln -s /home/pi/program/lib /home/pi/program/src/lib`

None of the above had any effect, the error message stays the same.

How can I include a file from another directory in my program?

# Answer
> 1 votes
This is definitely on the hacky side and not a proper solution to the problem, but it works nevertheless so I'm sharing it.

After making a symlink in the `/usr/share/arduino/libraries` directory you must make sure that there is a header file with the exact name of the directory, apparently that's how arduino is set up to include them.

In my case my symlink was named `GAVR`, so I had to create a `GAVR.h` file inside my `lib` directory, which would then go ahead and include my `i2c.h` file and possibly any other file that I'd need.

Also in `test.h` or anywhere I need to use `i2c.h` I must include `<GAVR.h>` instead.
Turns out Also 1 is false, you just need to include `<GAVR.h>` once in the `.ino` file and its members will be available everywhere, just like any other library.

Also 2, now that `ARDUINO_LIBS` is not empty in the `Makefile` you will need to manually declare *all* libraries that your code is using.

---
Tags: c, makefile, arduino-makefile
---


# Question
Title: Does the compiled binary of a sketch include uncalled functions from a library?
I am writing a GUI using a TFT display and the Adafruit GFX library and its default font on Arduino Nano. I want to be memory efficient and I assumed that the 'optimise for size' default setting of the compiler would not compile and include all functions from all included libraries if those functions are never called in the sketch.

However I was reading this memory management guide which advises (on pager 20) to remove 'unused libraries' and 'unused functions' from your sketch to save memory. So I have 2 related questions:

1. Does the Arduino IDE compiler include all the compiled binary from these library functions even if they are never called in the source sketch (I know that any global variables in a library will take space even if unused but I am specifically asking about unused functions)?
2. If that is the case would making my own modified, trimmed down, version of the standard libraries save space?

Thanks.

# Answer
In general only the functions actually used by your code are included in the final linkage of the binary.

However it's not always possible for the compiler to know what is used and what isn't.

In the case of simple functions and classes there's no problem - the linker is intelligent enough to work it out and only link in the functions that are actually used.

However when it comes to more complex systems with polymorphism or when working with function pointers there are times when the compiler won't really know what is needed and what isn't so sometimes some code gets included that isn't actually wanted.

As the compiler advances those times are getting fewer and farther between, so unless you really have a dire need to reduce your code size there's really nothing much to gain. If you do have that need then you would gain more by reducing the complexity of the code in general and collapsing any polymorphism rather than removing unused functions.

BTW: the "optimize for size" has nothing to do with what code is included / excluded. Instead it controls such things as which function are selected for `inline`, and what loops are *unrolled* or not, amongst other things.
> 6 votes

---
Tags: arduino-ide, memory-usage, code-optimization, memory, compiler
---


# Question
Title: Not output on serial monitor, sending string on serial.print
I get two 10-bit values from analog pins. These two values in a string, ";" combine with.

for ex: 515; 510

I am sending it to another arduino via Serial.print. I cannot display this string expression on other arduino's serial monitor. But when I press the reset button of Coordinator arduino, there are a few values. Can you help me?

My Coordinator Code:

```
#include <SoftwareSerial.h>
#define xBeeRxPin 10
#define xBeeTxPin 9
int deger3;
int deger4;
SoftwareSerial xBeeSerial(xBeeRxPin, xBeeTxPin);

void setup() {
  //Serial.begin(9600);
  xBeeSerial.begin(38400);
  }void loop() {

    deger3 = analogRead(A0);
    deger4 = analogRead(A2);

    String deger5 = " " + (String)deger3 + ";" + (String)deger4 ;

    Serial.println("string ifade: " + deger5);

    xBeeSerial.print(deger5);
  }

```

My Receiver Code:

```
#include <SoftwareSerial.h>
#define xBeeRxPin 10
#define xBeeTxPin 9
SoftwareSerial xBeeSerial(xBeeRxPin, xBeeTxPin);
String d1;

void setup() {
  xBeeSerial.begin(38400);
  Serial.begin(38400);
}
void loop() {
  if(xBeeSerial.available()){
    d1=xBeeSerial.readString();
    Serial.print(d1);
  }
}

```

# Answer
> 1 votes
I obtained the values I wanted and performed the separation. I am sending a list of joystick positions via the serial connection to the arduino in the following format

515;520

Which would be parsed as:

x=515

y=520

***MyCoordinator:***

```
#include <SoftwareSerial.h>
#define xBeeRxPin 10
#define xBeeTxPin 9
int deger3;
int deger4;
SoftwareSerial xBeeSerial(xBeeRxPin, xBeeTxPin);

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

}void loop() {
  xBeeSerial.begin(38400);
  deger3 = analogRead(A0);
  deger4 = analogRead(A2);

  String deger5 =  (String)deger3 + ";" + (String)deger4 ;
  Serial.println("string ifade: " + deger5);

  xBeeSerial.println(deger5);

  delay(200);
}

```

***MyReceiver:***

```
#include <SoftwareSerial.h>
#define xBeeRxPin 10
#define xBeeTxPin 9
SoftwareSerial xBeeSerial(xBeeRxPin, xBeeTxPin);
String d1,d2,d3;

void setup() {
  xBeeSerial.begin(38400);
  Serial.begin(38400);
}
void loop() {
  if(xBeeSerial.available()>0){
    d1=xBeeSerial.readStringUntil('\n');
    //Serial.print(d1);
    d2 = d1.substring(0,d1.indexOf(59));
    d3 = d1.substring(d1.indexOf(59)+1);
    Serial.println("x ekseni: " + d2);
    Serial.println("y ekseni: " + d3);
  }
}

```

# Answer
> 1 votes
There is a fundamental problem with your communication strategy, and that is you have nothing to tell the receiver "This is the end of a message".

You are sending a constant stream of

```
 515; 510 515; 510 515; 510 515; 510 515; 510 515; 510 515; 510 515; 510 515; 510 515; 510 515; 510 515; 510 515; 510 515; 510.....

```

and the receiver really doesn't know what to make of that.

This is because you are using the function `.readString()` at the receiver. This will blindly receive characters and store them in the target string up until the point those characters stop arriving. And that happens only after a break of at least 1 second in transmission. That never comes. So never ends. That is, until you reset the sender and it sees that break in transmission.

It's a very crude function and I'd never recommend anyone ever using it for anything.

Instead you need to break your transmission up into separate lines with `.println()` or appending `\n` to the string. Then you can use `.readStringUntil('\n')` to get each line in turn and display it.

Also, on a side note, you really shouldn't be appending all your data to a string then sending the string, that's completely redundant. Just send each individual part of the data as separate prints. All you're achieving with all that String manipulation is to fragment your heap and cause your code to be unstable.

---
Tags: arduino-uno, serial, softwareserial, data-type
---


title: My DHT22 module doesn`t work at all

text:
# Question
Title: My DHT22 module doesn`t work at all
I had bought this DHT22 module on AliExpress. The module looks fine, but it does not work at all. I had tried lots of sketches, I tried to change the pin, I tried to change the cables, but I always have the same result: `Failed to read from DHT22 sensor!`.

That's what I get if I use the standard sketch `DHTtester.ino`:

That's what I get if I use the standard sketch `DHT_Unified_Sensor.ino`:

Can you help me? Or is the module corrupted?

# Answer
The product page you linked to has modules of different types.

Make sure you have uncommented the matching type in the this section of the example:

```
// Uncomment whatever type you're using!
//#define DHTTYPE DHT11   // DHT 11
#define DHTTYPE DHT22   // DHT 22  (AM2302), AM2321
//#define DHTTYPE DHT21   // DHT 21 (AM2301)

```

Also makers of these boards sometimes label them incorrectly or describe them incorrectly when selling them. If you're unsure what you have, try them all.
> 0 votes

---
Tags: sensors, dht22
---


# Question
Title: Uno Wifi Rev2 Programming via Uno R3 ArduinoISP
I'm attempting to program Atmega4809 (Uno Wifi Rev2) via the ICSP pins on the board by connecting in this manner:

The difference is that I have a Uno Wifi Rev2 on the right instead of a Uno R3. I've uploaded the ArduinoISP sketch onto the Uno R3 on the left. Here is the `avrdude` command that I am using:

```
$ avrdude -v -patmega4809 -cavrisp -P /dev/ttyACM1 -b19200 -U program.elf

...

avrdude: AVR device initialized and ready to accept instructions

Reading |                                                    | 0% 0.00savr_read(): error reading address 0x0000
    read operation not supported for memory "signature"
avrdude: error reading signature data for part "ATmega4809", rc=-2
avrdude: error reading signature data, rc=-2

```

Full log: https://pastebin.com/LUfhsYeD

I am wondering if I am missing some difference between the UnoR3 and Uno Wifi Rev2... there doesn't seem to be much documentation about external programming of the Uno Wifi Rev2's Atmega 4809.

If it helps, my usecase for trying to program my Uno Wifi Rev2 externally is a need to reprogram the 32u4 as a HID. Once I program the 32u4, I won't be able to program the 4809 via USB (afaik).

If anyone knows what I'm doing wrong or the proper way to program the Uno Wifi Rev2 externally, your help would be greatly appreciated.

# Answer
> 1 votes
The new generation of AVR chips created by Microchip no longer use the same ICSP protocol as the old ones. Instead they use a new protocol called `updi`.

You need to use a different sketch and wiring to turn your Arduino into a suitable programmer. More information can be found here about how to do that.

---
Tags: programming, avrdude, arduinoisp, arduino-uno-wifi
---


# Question
Title: Help solving "collect2.exe: error: ld returned 1 exit status" error in code
I just got an Elegoo UNO starter kit the other day and have been working my way through the little tutorials on all the parts it came with. I am using VSCode with Platform.io plugin and (after getting it set up) it has been working nicely.

The code I am currently struggling with is a sketch that is supposed to use the IR Remote and Receiver the kit came with, I keep getting the error: `collect2.exe: error: ld returned 1 exit status`

I have done some looking around online but haven't had much luck getting anything to work.

My full code is below:

```
char foo;

#include <Arduino.h>
#include <IRremote.h>
#include <IRremoteInt.h>
#include <IR.h>

IRrecv irrecv(RECEIVER);     // create instance of 'irrecv'
decode_results results;      // create instance of 'decode_results'

void setup() {
  Serial.begin(9600);
  Serial.println("IR Receiver Button Decode");
  irrecv.enableIRIn();
}

void loop()
{
  int tmpValue;
  if (irrecv.decode(&results)) // have we received an IR signal?
  {
    for (int i = 0; i < 22; i++)
    {
      if ((keyValue[i] == results.value) && (i<KEY_NUM))
      {
        Serial.println(keyBuf[i]);
        tmpValue = results.value;
      }
      else if(REPEAT==i)
      {
        results.value = tmpValue;
      }
    }
    irrecv.resume(); // receive the next value
  }

//The implementation effect of the above program is
//the same as that of the following, but it is more concise

//    switch(results.value)
//  {
//  case 0xFFA25D: Serial.println("POWER"); break;
//  case 0xFFE21D: Serial.println("FUNC/STOP"); break;
//  case 0xFF629D: Serial.println("VOL+"); break;
//  case 0xFF22DD: Serial.println("FAST BACK");    break;
//  case 0xFF02FD: Serial.println("PAUSE");    break;
//  case 0xFFC23D: Serial.println("FAST FORWARD");   break;
//  case 0xFFE01F: Serial.println("DOWN");    break;
//  case 0xFFA857: Serial.println("VOL-");    break;
//  case 0xFF906F: Serial.println("UP");    break;
//  case 0xFF9867: Serial.println("EQ");    break;
//  case 0xFFB04F: Serial.println("ST/REPT");    break;
//  case 0xFF6897: Serial.println("0");    break;
//  case 0xFF30CF: Serial.println("1");    break;
//  case 0xFF18E7: Serial.println("2");    break;
//  case 0xFF7A85: Serial.println("3");    break;
//  case 0xFF10EF: Serial.println("4");    break;
//  case 0xFF38C7: Serial.println("5");    break;
//  case 0xFF5AA5: Serial.println("6");    break;
//  case 0xFF42BD: Serial.println("7");    break;
//  case 0xFF4AB5: Serial.println("8");    break;
//  case 0xFF52AD: Serial.println("9");    break;
//  case 0xFFFFFFFF: Serial.println(" REPEAT");break;
//  default:
//    Serial.println(" other button   ");

  }// End Case

```

This is code that was included with the tutorials, but I am not certain it is airtight as I have already had to do some tweaking of the code and header files included with the device. The error I am getting is the following:

```
include/IR.h:29:0: warning: "REPEAT" redefined
 #define REPEAT 22
 ^
In file included from src\main.cpp:4:0:
include/IRremote.h:57:0: note: this is the location of the previous definition
 #define REPEAT 0xffffffff
 ^
In file included from src\main.cpp:6:0:
include/IR.h:36:78: warning: initializer-string for array of chars is too long [-fpermissive]
                   "UP","EQ","ST/REPT","0","1","2","3","4","5","6","7","8","9"};
                                                                              ^
Linking .pio\build\uno\firmware.elf
C:\Users\wiley\AppData\Local\Temp\ccDVm6mB.ltrans0.ltrans.o: In function `global constructors keyed to 65535_0_main.cpp.o.1820':
<artificial>:(.text.startup+0x60): undefined reference to `IRrecv::IRrecv(int)'
C:\Users\wiley\AppData\Local\Temp\ccDVm6mB.ltrans0.ltrans.o: In function `main':
<artificial>:(.text.startup+0x160): undefined reference to `IRrecv::enableIRIn()'
<artificial>:(.text.startup+0x16c): undefined reference to `IRrecv::decode(decode_results*)'
<artificial>:(.text.startup+0x1c6): undefined reference to `IRrecv::resume()'
collect2.exe: error: ld returned 1 exit status
*** [.pio\build\uno\firmware.elf] Error 1

```

I don't understand the errors it is telling me are in the IR.h file. It says that REPEAT is redefined but it only defined once in the file. In regards to the `undefined reference to IRrecv::` I dont understand, because I have all the encessary files in the 'Include' folder, and when I CTRL click those functions in the editor it takes me to the files and shows me the code... so why can't it find the code when I run it?

IR.h:

```
#ifndef _IR_H
#define _IR_H

#define RECEIVER 11

#define KEY_POWER (0xFFA25D)
#define KEY_FUNC_STOP (0xFFE21D)
#define KEY_VOL_ADD (0xFF629D)
#define KEY_FAST_BACK (0xFF22DD)
#define KEY_PAUSE (0xFF02FD)
#define KEY_FAST_FORWARD (0xFFC23D)
#define KEY_DOWN (0xFFE01F)
#define KEY_VOL_DE (0xFFA857)
#define KEY_UP (0xFF906F)
#define KEY_EQ (0xFF9867)
#define KEY_ST_REPT (0xFFB04F)
#define KEY_0 (0xFF6897)
#define KEY_1 (0xFF30CF)
#define KEY_2 (0xFF18E7)
#define KEY_3 (0xFF7A85)
#define KEY_4 (0xFF10EF)
#define KEY_5 (0xFF38C7)
#define KEY_6 (0xFF5AA5)
#define KEY_7 (0xFF42BD)
#define KEY_8 (0xFF4AB5)
#define KEY_9 (0xFF52AD)
#define KEY_REPEAT (0xFFFFFFFF)
#define KEY_NUM 21
#define REPEAT 22

unsigned long keyValue[]={KEY_POWER,KEY_FUNC_STOP,KEY_VOL_ADD,KEY_FAST_BACK,KEY_PAUSE,KEY_FAST_FORWARD,
                KEY_DOWN,KEY_VOL_DE,KEY_UP,KEY_EQ,KEY_ST_REPT,KEY_0,KEY_1,KEY_2,KEY_3,KEY_4,KEY_5,
                KEY_6,KEY_7,KEY_8,KEY_9,KEY_REPEAT};

char keyBuf[][10]={"POWER","FUNC/STOP","VOL+","FAST BACK","PAUSE","FAST FORWARD","DOWN","VOL-",
                  "UP","EQ","ST/REPT","0","1","2","3","4","5","6","7","8","9"};
#endif

```

I have searched online a lot, and this seems to be a common issue with this IR.h library, and none of the fixes proposed have got me anywhere. (I get the same outputs when trying to run this sketch within the Arduino IDE with all a libraries installed)

I have been developing with Java and Python for a while now, but I have almost no experience with C or C++ before the Arduino, so maybe this is a simple error I just don't understand. Super frustrating!! Any help or guidance would be appreciated! Thanks

# Answer
I have figured it out.

The problem was I had not properly set up the project with the proper libraries. I thought I was doing it right manually but I was not. PlatformIO has a really convenient Library manager that helps with set up. You just select a library and it will automatically add it to the project you choose and make sure the correct dependencies are listed in the .ini file. I was trying to manually drop the files I needed into the correct directories, and was not doing the proper adjustments to the .ini file. Thanks for the help @Mat!
> 2 votes

---
Tags: arduino-uno, ir, debugging, vscode, platformio
---


# Question
Title: How to assign text stored in a local file to a string at compile time
I'm developing a program that uses the HTML server in the WiFi101 library.

My hardware does not have SD card storage so all source html needs to be stored as strings in the sketch at compile time. To aid in development I want to keep my html files separate from the sketch and include them at compile time.

Is there a way to use #include in the Arduino IDE and assign the included file to a string/char array constant? If so can the path to the included file be relative to the sketch's path?

Notes: Similar question on Stack overflow: https://stackoverflow.com/questions/410980/include-a-text-file-in-a-c-program-as-a-char

Edit: There are lots of great answers here to solve this in a more robust fashion. The correct thing to do is setup a proper build system. If I were to set this up I'd be temped to try something like Gulp since you could easily minify/lint your web content. As this is a small project I ended up just running the HTML through a minifier service and copy/pasted into strings.

# Answer
> 1 votes
This will probably not work with the Arduino IDE. If you are willing to go through a Makefile-based workflow, you can install this generic Arduino Makefile, which should make things easier.

With that Makefile installed in `/usr/share/arduino/Arduino.mk`, the following test worked on an Arduino Uno. It is based on the objcopy trick from the article Embedding of binary data into programs.

Project's **Makefile**:

```
BOARD_TAG    = uno
MONITOR_PORT = /dev/ttyACM0
OTHER_OBJS   = text.o

include /usr/share/arduino/Arduino.mk

text.o: text.txt
    avr-objcopy -I binary -O elf32-avr -B avr:5 $< $@

```

**text.txt**:

```
Hello, World!

```

**include-blob.ino**

```
extern "C" const uint8_t _binary_text_txt_start[];
extern "C" const uint8_t _binary_text_txt_size;

void setup() {
    Serial.begin(9600);
    Serial.write(_binary_text_txt_start, (size_t) &_binary_text_txt_size);
}

void loop(){}

```

The program just prints “Hello, World!”, but if you modify text.txt and retype `make`, it will print whatever you had in this file. Please note that the text is not NUL-terminated, so you have to use the `_binary_*_size` symbol to know its size.

# Answer
> 5 votes
I found another way to include a literal file (html, css, or other) and assign it to a constant string without resorting to make files:

Add one line of code on top of your html (css, js, etc) file, and another at the bottom, and save it with an extra .h extension. Then include that file in de Arduino IDE. This could easily be done by a (manually executed) script, every time those files are changed.

```
const char *indexHtml = R"====( // added by script
<html> <!-- original .html file -->
.
.
.
</html> <!-- end .html -->
)===="; // added by script

```

The variable name can be derived from the original filename. The result is saved with an extra .h extension. In the .ino (or .cpp) you can then include this file:

```
#include index.html.h

```

This will compile in the Arduino IDE.

# Answer
> 1 votes
C++ has 'raw string literals'. You can put a constant string, without escaping special characters, into the source code between an opening and closing 'tag'. You can choose the tag to be something that is not in the raw string. In following example the tag is `=====`.

```
const char* s1 = R"=====(Hello
"World")=====";

```

is same as

```
const char* s2 = "Hello\n\"World\"";

```

This way you can put your large strings into separate .h files and include them. On AVR use PROGMEM to save RAM.

# Answer
> 0 votes
An easy way to do this is to write a C program to convert your files that you want included into your source into a form that looks like:

```
byte file_001[] = { 0x00, 0x01, 0x02, 0x04, 0x0A, 0x00, 0x01, 0x02, 0x04, 0x0A,
                    0x01, 0x01, 0x02, 0x04, 0x0A, 0x00, 0x01, 0x02, 0x04, 0x0C,

                    ...

                    0x03, 0x01, 0x02, 0x04, 0x0A, 0x00, 0x01, 0x02, 0x04, 0x0C };

```

The converted file can contain binary data without issue instead of just ASCII.

You can then access the file directly using: file\_001\[index\]

---
Tags: c, web-server
---


# Question
Title: What are a few good ways to connect multiple I2C busses?
I have an issue with a project. I have a backplane with an Atmega328P based microcontroller controlling an I2C bus with multiple peripheral devices. One such peripheral is a removable card with another Atmega328P based microcontroller as the peripheral. I have a TCA4311ADR I2C hotswap buffer on the backplane connected to the port that connects to the card. The card is supposed to be a peripheral device that sends processed data from a sensor to the backplane.

Here’s my issue: one of the sensors I intend to use on the card is an I2C breakout board. To control it, the microcontroller on the card needs to act as a controller, but it also needs to be a peripheral to communicate with the backplane controller. Every time I try to make this work and the card tries to communicate with the sensor, it tries to start a new I2C bus and everything starts glitching.

I’ve tried a few options. Software used to turn normal digital pins into I2C pins didn’t work since the libraries don’t seem compatible. I can’t seem to get the card peripheral to wait until the controller starts the bus before trying to control the sensor to avoid a conflict.

I had an idea to use an I2C multiplexer like the TCA9543A to create two busses but I don’t know if that would work. I also don’t wanna just use SPI or Serial to connect the microcontrollers cause I’d have to undo months of work on coding and custom PCBs. Also using Serial would complicate the connection to the computer and using SPI wouldn’t work if I use an SPI sensor breakout later.

Is there any other way to make this system work?

# Answer
In an ideal world you would have your other sensor on a separate I2C bus. It *can* be done with software, but chances are you will have to re-write the library that supports it to use bit-banged I2C.

Yes, you could use an I2C MUX to share the single hardware I2C channel, however that will both be awkward and the results will be sub-optimal anyway.

Most I2C MUX chips, including the TCA9543A, are controlled themselves by I2C, so you can't really use them in your environment, since you really need to switch it to isolate your main bus from the MCU *before* you switch it from slave to master, which you can't do until *after* you have switched it from slave to master. If you switch to master before isolating the bus you risk a collision with the main master on the bus and everything going horribly wrong.

These MUX chips are really designed for allowing one master to talk to multiple slaves that share the same addresses.

And on top of that when you've isolated the bus the main master will no longer be able to communicate with that slave board, which will either cause the whole bus to lock up or other strange and unwanted things to happen.

So have another go at using software I2C to communicate with your sensor. Most I2C communication to sensors is pretty straightforward and follows the same rough format, so it really shouldn't be too hard to implement.

Either that or consider replacing the ATMega328P with a more capable microcontroller that has multiple I2C busses.
> 1 votes

---
Tags: i2c, library, atmega328, spi, multiplexer
---


title: NRF24l01 Channel switching

text:
# Question
Title: NRF24l01 Channel switching
I have a NRF24L01 radio module. The description indicates that it can work in the ISM frequency range of 2.400 ... 2.525 GHz. The channel step is 1 MHz, and there are 125 channels in total.

The channel number can be set using **radio.setChannel (0x125);** The maximum number is supposedly 125. However, I examined the signal spectrum in Sdrsharp using a radio tuner and it turned out that the frequency at the maximum channel is very low.

I started increasing the number and got to 180 **radio.setChannel (125);** the frequency was 2525 MHz as stated. It turns out that the number of channels of the radio module is not 125, but 180? I determined the 180 number experimentally. The literature says that it has 125 channels 1 MHz wide. The most interesting thing is that the Arduino IDE does not give errors when entering a large number of channels. Tell me how you can speed up the process of switching channels in order to understand how they switch. To manually reflash it for a long time when changing each channel.

```
#include <SPI.h>
#include "nRF24L01.h"
#include "RF24.h"

RF24 radio(9, 10); // use 9 и 10 pin arduino uno
byte address[][6] = {"1Node", "2Node", "3Node", "4Node", "5Node", "6Node"};
byte counter = 1;

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

  radio.begin(); //activate module
  radio.setAutoAck(0); //confirmation mode, 1 on 0 off
  radio.setRetries(0, 15); //(time between attempts to reach out, number of attempts)

  radio.setPayloadSize(32); //packet size, in bytes

  radio.openWritingPipe(address[0]); //we are pipe 0, we open a data channel
  radio.setChannel(125); //select a channel (in which there is no noise!) 0 ... 125

  radio.setPALevel (RF24_PA_MIN); //transmitter power level. To choose RF24_PA_MIN, RF24_PA_LOW, RF24_PA_HIGH, RF24_PA_MAX
  radio.setDataRate (RF24_2MBPS); //exchange rate. To choose RF24_2MBPS, RF24_1MBPS, RF24_250KBPS
  radio.powerUp(); //get started
  radio.stopListening(); //do not listen to radio broadcasts, we are a transmitter
}

void loop(void) {
  while (1)
  {
    radio.write(&counter, 1);
    //Serial.println(counter);
  }
}

```

Is it possible to toggle the channel number **radio.setChannel (0x180)** sequentially in a void loop? thanks!

I tried to do this:

```
void loop (void) {
     for (int n = 0; n <126; n ++)
     {
       radio.setChannel (n); // select a channel (in which there is no noise!) 0 ... 125
       radio.write (& counter, 1);
       delay (1000);
     }
}

```

However, **radio.write (& counter, 1)** should work separately from any loops to avoid delays. Otherwise, it doesn't work correctly.

# Answer
You're getting confused with number bases. A number prefixed with `0x` is hexadecimal. That's base 16 - not base 10.

0x125 is actually 293. If you try squeezing 293 into an 8-bit register it will truncate to 37.

Channel 125 is 0x7D in hexadecimal.

I can't recall off hand how big the register is for the channel number, but either 7 or 8 bits would suffice (probably only 7 bits actually used) so the highest channel number you could possibly enter would be 127, which is 0x7F, after which it will start at channel 0 again for 128 or 0x80.
> 2 votes

---
Tags: arduino-ide, nrf24l01+
---