body:
I have a project where I need to monitor the state of 5 DPDT electrical switches with Arduino Uno. Also, the Arduino board will be measuring the output from 3 thermocouples on 3 of the analogue pins as input and sending signals to open and close 3 relays for heaters on the 3 of the digital pins as output. The data with the state of the microswitches and the measurements from the thermocouples will be send over a serial connection to a PC.

I think I need a shield with at least 20 inputs for monitoring the 5 DPDT electrical switches (5 x 2 x 2). The common of the switches will be connected to a common rail. Can I use an I2C extension shield for this purpose? Is this going to create an issue with the serial connection? Any specific shield recommendations?

title: Recommend an Arduino Uno shield to monitor the state of 5 DPDT electrical switches

Answers: 1

body:
If you're really set on measuring the state of every single connection of every single switch (though I still don't see the need) then yes, you'll need 20 IO connections.

You could create those with IO expanders (MCP23017 for example), or you could use multiplexing.

Instead of 4x5 (20) IO pins you'd instead need 2+10 (12) IO pins.

Treat all the "Common" connections as the rows of a keypad and all the NC and NO connections as the columns of a keypad. Add a smattering of diodes to isolate everything, and you can then scan through the switches one at a time checking each of the two switch states.

You can read more about keypad matrices [here](https://www.gammon.com.au/forum/?id=14175).


body:
For INA3221 current sensor, I found this [library](https://github.com/switchdoclabs/SDL_Arduino_INA3221), however, I don't understand how to use the `INA3221SetConfig()` function as defined in the .cpp file [link](https://github.com/switchdoclabs/SDL_Arduino_INA3221/blob/master/SDL_Arduino_INA3221.cpp).

    void SDL_Arduino_INA3221::INA3221SetConfig(void)
    {

          // Set Config register to take into account the settings above
          uint16_t config =
              INA3221_CONFIG_ENABLE_CHAN1 |
              // INA3221_CONFIG_ENABLE_CHAN2 |
              // INA3221_CONFIG_ENABLE_CHAN3 |
              INA3221_CONFIG_RESET |
              INA3221_CONFIG_AVG1 |
              INA3221_CONFIG_VBUS_CT2 |
              INA3221_CONFIG_VSH_CT2 |
              INA3221_CONFIG_MODE_2 |
              INA3221_CONFIG_MODE_1 |
              INA3221_CONFIG_MODE_0;
          wireWriteRegister(INA3221_REG_CONFIG, config);
        }

It seems like the function is called automatically when the `.begin()` function is called and whatever is defined in the config function is written to the register. The use of | operator confuses me. I tried to comment out the some settings to see if it works but it makes no difference. There isn't any documentation so I am in a fix. Could you please tell how can I change the configuration settings e.g. instead of all the three channels or change the config_mode?

title: How to use this confing function

Answers: 1

body:
Without looking at the library, you can check yourself if this method (`INA3221SetConfig`) is called from the `begin` method (of the same class). Just trace back the methods manually until you find a call to this method.

About the `|` or 'bit-wise-or' operator (see https://en.wikipedia.org/wiki/Bitwise_operations_in_C), these are used to set bits in a byte/word/long.

Most registers have 8, 16 or 32 bits and with the `|` operator you can easily set multiple bits at the same time. Each value (e.g. `INA3221_CONFIG_ENABLE_CHAN`) has a value that is a power of 2 (mostly defined in the form `1 << ..something..` you can add them (with +) or `|` them together, but | is more clear what the purpose is and repeatedly calling `|` the same bit twice is not a problem (it still gives the same result).


body:
I bought a bunch of VL530X time-of-flight sensors on Aliexpress. They seemed to work fine. Then I connected two of them on the same Arduino Uno board to test with the Adafruit example "dual". During rewiring I may have used the 5v power pin of the Arduino instead of the 3.3v (I can't remember).

Now the sensors won't boot. They fail during setup with error -6 which is documented as "RANGE ERROR".

Yet, scanning for either of them does find a sensor at the default address 0x29.

How can one know if they're dead or if they can somehow be revived?

The Uno works fine with any other VL53L0x, just not those two. I could certainly just trash the ones that won't boot but I would be interested in a procedure to know for sure; it would be very useful when going into production.

The [last answer on this thread an ST forum](https://community.st.com/s/question/0D53W00000BIk0B/vl53l0x-stopped-working-suddenly-) points to the I2C bus, but I don't understand what is being recommended.

title: How to know if a tof VL53L0x sensor is dead or not

Answers: 0


body:
OS: Mac
Arduino: 1.8.13
Keyboard Library: 1.0.2

[![ESP8266][1]][1]

I have a generic ESP8266 board, and I have the following code

    void setup() {
      // put your setup code here, to run once:
      pinMode(LED_BUILTIN, OUTPUT);
      Keyboard.begin();
    }

    void loop() {}

However I get the following ouput:

> In file included from /Users/quba/Sandbox/sketch_feb07a/sketch_feb07a.ino:1:0:

/Applications/Arduino.app/Contents/Java/libraries/Keyboard/src/Keyboard.h:25:17: fatal error: HID.h: No such file or directory

 #include "HID.h"

                           ^

compilation terminated.

exit status 1

Error compiling for board Generic ESP8266 Module.

Could not find boards.txt in /Users/quba/Library/Arduino15/packages/arduino/hardware/megaavr/1.8.7. Is it pre-1.5?

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

title: ESP8266: #include <Keyboard.h> causes fatal error: HID.h: No such file or directory

Answers: 1

body: The Keyboard library is for Arduino ATMega32U4 based Arduinos (and other similar ones with USB) only. The ESP8266 does not have USB, so how can it possibly use the Keyboard library?


body:
I am building a solution with an ESP32, a PAM8403 amp, a parallel TFT display, and a RFM95 LoRa module. All works great but I want to get rid of the noise that is generated when Lora is in receive mode.

I can do this by pulling pin 12 low on the PAM8403, which mutes all sound. However I have ran out of output pins on my ESP32, and it's too late to use a IO expander as the PCB has been built.

My initial idea was to use the RX/TX pins on the ESP32 when the unit was out of diagnostics mode. However if I can avoid this then that would be great. In my code when I issue `Lora.sleep() / Lora.idle()` the hissing goes away.

So I started to wonder if I could just trigger the mute function through another logic state that goes low when LoRa is idle and high when sleeping (allowing the mute to deactivate).

I am using the `LoRa` library by Sandeep Mistry, and I was wondering if I could use `DIO1, DIO2`, etc. as an IO PIN to control mute. If not, is it possible to use any of the already connected pins to behave in the desired way?

Thanks all in advance!

title: RFM95 digital io to control mute on PAM8403 to get rid of hiss while receiving

Answers: 1

body:
No, there is no way you can use the DIO pins to indicate sleep mode. They can only be set to indicate certain events, and sleep/idle is not one of them.

However the nRESET pin is optional, and you can use the `setPins()` function in the LoRa library to change which pin it's connected to - and one option is to set it to `-1` in which case the library ignores it (this must be run *before* `.begin()` is called) as it's only used during `begin()` to initially reset the LoRa module.

You could either tie nRESET HIGH (to 3.3V) to never reset it, or couple it with the reset signal of another peripheral so it gets reset at the same time - just be careful with your initialisation order in this case so you don't reset the module after configuring it...


body:
i am making a project using Arduino Uno that display data on 7 seg display which stored in SD card as day by day. when i make power ON to device then SD card initialization done & data shows correct as per date. Then after when i change the date SD card failed i.e. "show error opening database.txt" .

How can i overcome with this?

" When debugging my SD Card I had a software error that would put the
card into a state that required the microSD card to be powered down and then
powered up to work. It would work until the software error and then not
work again until the power was cycled. "

title: SD card initialize and fails when date changed

Answers: 0


body:
I'm trying to connect paj7620 to nodemcu micro-controller. I have implemented the following code and it worked perfect on arduino uno. The problem is that I was made to migrate to nodemcu.

Here is my code:

```
/*
 * Copyright (c) 2015 seeed technology inc.
 * Website    : www.seeed.cc
 * Author     : Wuruibin
 * Modified Time: June 2015
 * Description: This demo can recognize 15 gestures and output the result.
 *     You can adjust the reaction time according to the actual circumstance
 *    by modifying "#define GES_REACTION_TIME  500".
 *
 * The MIT License (MIT)
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 */
#include <ESP8266WiFi.h>
#include <Wire.h>
#include "paj7620.h"

/*
Notice: When you want to recognize the Forward/Backward gesture or other continuous gestures, your gestures' reaction time must less than GES_REACTION_TIME(0.8s).
        You also can adjust the reaction time according to the actual circumstance.
*/
#define GES_REACTION_TIME  800
#define GES_QUIT_TIME   1000

void setup()
{
 uint8_t error = 0;

 Serial.begin(9600);
 Serial.println("\nPAJ7620U2 TEST DEMO: Recognize 15 gestures.");

 error = paj7620Init();   // initialize Paj7620 registers
 if (error)
 {
  Serial.print("INIT ERROR,CODE:");
  Serial.println(error);
 }
 else
 {
  Serial.println("INIT OK");
 }
 Serial.println("Please input your gestures:");
    Serial.begin(115200);
  Serial.println();

  // Serial.print("Setting soft-AP configuration ... ");
  // Serial.println(WiFi.softAPConfig(local_IP, gateway, subnet) ? "Ready" : "Failed!");

  Serial.print("Setting soft-AP ... ");
  Serial.println(WiFi.softAP("NODEMCU") ? "Ready" : "Failed!");

  Serial.print("Soft-AP IP address = ");
  Serial.println(WiFi.softAPIP());
}

void loop()
{
 uint8_t data = 0, data1 = 0, error;

 error = paj7620ReadReg(0x43, 1, &data);    // Read Bank_0_Reg_0x43/0x44 for gesture result.
 if (!error)
 {
  switch (data)          // When different gestures be detected, the variable 'data' will be set to different values by paj7620ReadReg(0x43, 1, &data).
  {
   case GES_RIGHT_FLAG:
    delay(GES_REACTION_TIME);
    paj7620ReadReg(0x43, 1, &data);
    if(data == GES_LEFT_FLAG)
    {
     Serial.println("Right-Left");
    }
    else if(data == GES_FORWARD_FLAG)
    {
     Serial.println("Forward");
     delay(GES_QUIT_TIME);
    }
    else if(data == GES_BACKWARD_FLAG)
    {
     Serial.println("Backward");
     delay(GES_QUIT_TIME);
    }
    else
    {
     Serial.println("Right");
    }
    break;
   case GES_LEFT_FLAG:
    delay(GES_REACTION_TIME);
    paj7620ReadReg(0x43, 1, &data);
    if(data == GES_RIGHT_FLAG)
    {
     Serial.println("Left-Right");
    }
    else if(data == GES_FORWARD_FLAG)
    {
     Serial.println("Forward");
     delay(GES_QUIT_TIME);
    }
    else if(data == GES_BACKWARD_FLAG)
    {
     Serial.println("Backward");
     delay(GES_QUIT_TIME);
    }
    else
    {
     Serial.println("Left");
    }
    break;
    break;
   case GES_UP_FLAG:
    delay(GES_REACTION_TIME);
    paj7620ReadReg(0x43, 1, &data);
    if(data == GES_DOWN_FLAG)
    {
     Serial.println("Up-Down");
    }
    else if(data == GES_FORWARD_FLAG)
    {
     Serial.println("Forward");
     delay(GES_QUIT_TIME);
    }
    else if(data == GES_BACKWARD_FLAG)
    {
     Serial.println("Backward");
     delay(GES_QUIT_TIME);
    }
    else
    {
     Serial.println("Up");
    }
    break;
   case GES_DOWN_FLAG:
    delay(GES_REACTION_TIME);
    paj7620ReadReg(0x43, 1, &data);
    if(data == GES_UP_FLAG)
    {
     Serial.println("Down-Up");
    }
    else if(data == GES_FORWARD_FLAG)
    {
     Serial.println("Forward");
     delay(GES_QUIT_TIME);
    }
    else if(data == GES_BACKWARD_FLAG)
    {
     Serial.println("Backward");
     delay(GES_QUIT_TIME);
    }
    else
    {
     Serial.println("Down");
    }
    break;
   case GES_FORWARD_FLAG:
    delay(GES_REACTION_TIME);
    paj7620ReadReg(0x43, 1, &data);
    if(data == GES_BACKWARD_FLAG)
    {
     Serial.println("Forward-Backward");
     delay(GES_QUIT_TIME);
    }
    else
    {
     Serial.println("Forward");
     delay(GES_QUIT_TIME);
    }
    break;
   case GES_BACKWARD_FLAG:
    delay(GES_REACTION_TIME);
    paj7620ReadReg(0x43, 1, &data);
    if(data == GES_FORWARD_FLAG)
    {
     Serial.println("Backward-Forward");
     delay(GES_QUIT_TIME);
    }
    else
    {
     Serial.println("Backward");
     delay(GES_QUIT_TIME);
    }
    break;
   case GES_CLOCKWISE_FLAG:
    Serial.println("Clockwise");
    break;
   case GES_COUNT_CLOCKWISE_FLAG:
    Serial.println("anti-clockwise");
    break;
   default:
    paj7620ReadReg(0x44, 1, &data1);
    if (data1 == GES_WAVE_FLAG)
    {
     Serial.println("wave");
    }
    break;
  }
 }
 delay(100);
}
```

```
------------------------
|paj7620    | nodemcu  |
------------------------
| VCC       | 3.3v     |
------------------------
| GND       | GND      |
------------------------
| SCL       | D1       |
------------------------
| SDA       | D2       |
------------------------
```

After connecting the ports like the above table, I get the following error when I am trying to upload the code on nodemcu.

Would someone help me how to resolve this error?

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

**Wiring**
[![enter image description here][2]][2]

**PS** I have also tried [I2C Scanner](https://playground.arduino.cc/Main/I2cScanner/) as @timemage mentioned in comments.

[![enter image description here][3]][3]

**PS 2** It works properly when I connect the paj7620 to arduino compiling the above code.

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

**output:**
[![enter image description here][5]][5]

  [1]: https://i.stack.imgur.com/yek2q.png
  [2]: https://i.stack.imgur.com/JO9OG.jpg
  [3]: https://i.stack.imgur.com/VmCbG.png
  [4]: https://i.stack.imgur.com/H5Ll3.jpg
  [5]: https://i.stack.imgur.com/vRN7m.png

title: can't connect paj7620 (gesture detector module) to nodemcu

Answers: 2

body:
You've gotten rather quiet over there since I suggested zooming in on your sensor board.  Just so this question doesn't circulate around in the system for years, here's *an* answer:

[![Zooming in on poorly soldered header.][1]][1]

Your soldering should closer to this.  Hopefully better, as these are ones I did:

[![Soldering][2]][2]

The solder short of sort web-up the sides of the pins. The use the term "fillet" for that.  Where your pads around the through-hole looks broader than the ones that are on the board above, it should probably look a bit better.  **There shouldn't be unfilled parts of the through-hole**, in any case.  At least not on the side you're soldering.

I expect it will at least show in the I2C scanner when you fix that.  It *may* show a different address from what is default in the library, in which case you may need to tell it to use the address that shows in the scanner.

  [1]: https://i.stack.imgur.com/xyETc.jpg
  [2]: https://i.stack.imgur.com/Ot9qN.jpg

body:
Special thanks to @timemage for his support. After struggling with the board for more than 6 hours it works properly. I will describe and give more details about how the problem was solved later on.

Arduino Uno has 5 Analog inputs, while there isn't any of them on nodemcu. To connect paj7620 to nodemcu, it is noticable that as @timemage said:
> "The A4 and A5 on the UNO are where the ATMega328P's I2C bus signals happen to be. Earlier versions of the Arduino UNO and related boards didn't have dedicated SDA and SCL headers as they do now. On those UNO that have SDA and SCL pins on the upper digital header, they are the same exact signal as those found on A4 and A5."

So the first schema was correct.

As it is implied from the fifth page of [this link](https://github.com/nodemcu/nodemcu-devkit-v1.0/blob/master/NODEMCU_DEVKIT_V1.0.PDF) there isn't any difference among 3.3v inputs on nodemcu. But I have changed wiring like the following image and it works!

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

```
#COLOR MAPPING
RED: VCC - 3.3v
BLACK: GND
ORANGE: SCL - D1
GREEN: SDA - D2
```

I hope it helps, cause there isn't any way to trace the problem. :)

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


body:
I'm using an Arduino Due that talks via SPI to an LCD (800x480) with the RA8875 controller chip.
The most recent datasheet I could find is: [RA8875 datasheet][1].
Everything works as expected when using the Adafruit library. But, for my project, I want to maximize the communication speed between the LCD and the Arduino DUE.

Page 60 of the datasheet tells me that the maximum SPI speed to perform a SPIread is
> system clock / 6.

Page 39 gives the formula for the system clock:
> SYS_CLK = FIN * ( PLLDIVN [4:0] +1 ) / (( PLLDIVM+1 ) * ( 2^PLLDIVK [2:0] ))

There are some constraints:

1. From page 39:
FPLL = FIN * ( PLLDIVN [4:0] +1 ) must be equal to or greater
than 110 MHz

2. From page 91:
For an LCD of dim 800x480 2 layers 8bit color depth 60Hz framerate the pixel clock should be between  30 and 33MHz. (Registers are set to have 2 layers and 8 bit color depth).

A crystal of 20Mhz is soldered on the LCD ( FIN = 20 Mhz)

I have set the registers as follows:

| Register   | Value|
|------------|------|
| PLLC1[88h] | 24   |
| PLLC1[89h] | 1    |
| PCSR[04h]  | 3    |

So, I expect:
* SYS_CLK  = 20 Mhz * ( 24 +1 ) / (( 0+1 ) * ( 2^1 )) = 250 Mhz
* Pixel clock = SYS_CLK / ( 2^3 ) = 31.25 Mhz
* Max. spi speed = 250 Mhz / 6 = 41.66 Mhz.

I think to obey every given constraint.
But when I use an spi-speed of 30 Mhz, which is below 41.66 Mhz, I get a black screen.

I've put the Arduino sketch and the modified Adafruit library (Sven_RA8875) on google drive:
[Arduino sketch + modified library][2].

The same data but on a pastebin:

[Image: Working LCD at 20 Mhz][3]

[Example code RA8875][4]

[Modified library .cpp][5]

[Modified library .h][6]

**Edit by PPK:**
I add the pictures from paste pics to this post after I scaled and croped them.

[![Osci display with 20 MHz setup][7]][7]

[![Osci display with 30 MHz setup][8]][8]
[![Osci display with 30 MHz setup][9]][9]

  [1]: https://www.buydisplay.com/download/ic/RA8875.pdf
  [2]: https://drive.google.com/drive/folders/1h39YVdIvks6dtk26aTGCVAaoNjGIF6fB?usp=sharing
  [3]: https://paste.pics/2ccbf9b548cfb4cafbed49252d9b626c
  [4]: https://paste.c-net.org/SnowingWhich
  [5]: https://paste.c-net.org/BaptismJupiter
  [6]: https://paste.c-net.org/AnwarRecall
  [7]: https://i.stack.imgur.com/99tcu.png
  [8]: https://i.stack.imgur.com/AtOvi.jpg
  [9]: https://i.stack.imgur.com/fgITO.jpg

title: Black screen when using higher SPI-speed for RA8857 LCD-controller

Answers: 0


body:
I'm working on a few arduino projects where I've needed a flexible scheduler and/or timer library and was wondering if anyone has a library they recommend?

**Case 1:**
I have a sensor that needs to collect observations every hour, but it has a specific  measurement sequence:
- Power up/boot (takes about 15 seconds)
- Warm-up for 60 seconds.
- Observe (2 min), collect raw data, generate stats
- Cool-down for 5 min.
- Power off

In this case have a single micro-controller acting as a data-logger that is controlling multiple sensors and writing to an SD card.

**Case 2:**
I have an oven that needs to be controlled to a user-specified temperature profile (up say to 6 points of change), i.e.:
- Turn on heater
- Set temperature, 100C and hold for 2 min
- Set temperature, 160C and hold for 15 min
- Set temperature, 250C and hold for 1 hr
- ....
- Set temperature, 100C and hold for 1 hr
- Turn off heater

I'm familiar with non-blocking timers and (in the past) have cobbled together a few simple timers with millis() and some ulong variables. Alas, the complexity and debugging time rapidly grows with the number of dependent timers. Before I sit down and sketch out a class definition, I figured I'd ask what others are using.

title: LF: flexible scheduler/timer library

Answers: 1

body:
Some libraries I find good (opinion-based):

* TaskManagerIO: https://github.com/davetcc/TaskManagerIO
   * does a good job at managing events / scheduling things for a certain (system) time, or even repetitively.
   * with that you could e.g. use a `scheduleFixedRate()` API to call a function every 60 minutes. Then starts the power up (I assume asynchronously, by setting a pin or something), and just primes the scheduler with the `scheduleOnce()` API to call another function in 15 seconds. That target function then starts the warmup and schedules the next function / step for 60 seconds into the future, et cetera. It would express the flow very naturally.
* If accurate timekeeping is needed so that it's really every hour, you might want to  use an external RTC module. Also depends on the microcontroller you're using, many have a builtin one that you can feed with a 32.768 kHz crystal and thus you don't need an external chip
  * library for the DS3231 / DS3232 RTC lets you set an alarm in the RTC: https://github.com/JChristensen/DS3232RTC/blob/master/alarm-primer.md
   * with that you can e.g. set an alarm for every 60 minutes and then execute your task.


body:
I am trying to build a wireless switch. At one end, I have Arduino Uno connected to Nrf24l01+pa+lna module. While at the other end there is Arduino Nano connected to Nrf24l01+pa+lna and a relay. I send char '1' or '0' through Nrf24l01 attached to Arduino Uno. Nrf24l01 attached to  Arduino Nano  receives this char and turns on or off the relay connected to Pin D3 of Arduino Nano. The my Arduino Nano replies back as '1' or '0'. Uno receives it and displays it on serial monitor.
At start the communication sometimes worked and sometimes didn't. Then I connected a 10uF capacitor to the both Nrf24l01 modules. Now I am receiving 00 Hex and relay is also not responding. Can any one help. Code is attached.

```
// Arduino Uno Code
#include <SPI.h>
#include <nRF24L01.h>
#include <RF24.h>

RF24 radio(7, 8); // CE, CSN
const byte addresses[][6] = {"00001", "00002"};

char serialChar;
char motorChar;

void setup() {
  Serial.begin(9600);
  radio.begin();
  radio.openWritingPipe(addresses[1]); // 00002
  radio.openReadingPipe(1, addresses[0]); // 00001
  radio.setPALevel(RF24_PA_MIN);
}

void loop() {
    radio.stopListening();
    if (Serial.available() > 0) {
      serialChar = Serial.read();
      radio.write(&serialChar, sizeof(serialChar));

      delay(5);
      radio.startListening();
      while (!radio.available());
      radio.read(&motorChar, sizeof(motorChar));
      Serial.print(motorChar);
    }
}
```
```
//Arduino Nano Code
#include <SPI.h>
#include <nRF24L01.h>
#include <RF24.h>

RF24 radio(7, 8); // CE, CSN
const byte addresses[][6] = {"00001", "00002"};
char command;
int relayPin = 3;

void setup() {
  radio.begin();
  radio.openWritingPipe(addresses[0]); // 00001
  radio.openReadingPipe(1, addresses[1]); // 00002
  radio.setPALevel(RF24_PA_LOW);

  pinMode(relayPin,OUTPUT);
  digitalWrite(relayPin, HIGH); // Relay is Now Off
}

void loop() {
    delay(5);
    char state = '0'; // switch is off
    radio.startListening();

    if (radio.available()) {
      radio.read(&command, sizeof(command));
      if(command == '1'){
        digitalWrite(relayPin,LOW); // Relay is Now On
        state = command;
        delay(5);
        radio.stopListening();
        radio.write(&state, sizeof(state));
      }
      else if (command == '0'){
        digitalWrite(relayPin, HIGH); // Relay is Now Off
        state = command;
        delay(5);
        radio.stopListening();
        radio.write(&state, sizeof(state));
      }
      else{
        delay(5);
        radio.stopListening();
        radio.write(&state, sizeof(state));
      }

    }
}
```

title: Problem communicating Using Nrf24l01+pa+lna, I am receiving 00 Hex

Answers: 0


body:
The project I'm planning is to use a NodeMCU at each electrical board in house to control lights and fans via relays. Each MCU will communicate via MQTT over WiFi to a Raspberry Pi 4 from where I can control all lights and fans in the house. My doubt is:

Can the 3.3V NodeMCU drive a 5V relay like this [1 Channel 5V Relay Module with Optocoupler][1] since I can't find any 3.3 V relays in India. Or must I use a logic level shifter? Or just use an ESP32 board (double price).

  [1]: https://www.electronicscomp.com/1-channel-5v-relay-module

title: Help with NodeMCU based smart switch

Answers: 1

body: The relay I linked to couldn't be operated with 3v3 from the NodeMCU board. I was powering the NodeMCU via a breadboard power supply that had both 3v3 and 5v output (https://www.electronicscomp.com/mb102-breadboard-power-supply-module). I connected the Vcc and GND of relay to 5V supply on that module. the IO pin relay was connected to NoddeMCU. It worked fine and NodeMCU could switch it on and off.


body:
For the below code snippet
```
const char* fr_fbdb(char tag[30]) // fn for retrieving data
{
  char full_path[120];
  const char *_dt ;
  strcpy(full_path , base_path);
  strcat(full_path , tag);
  Serial.print( "retrieving from " );
  Serial.println(full_path) ;
  Firebase.get(firebaseData, full_path);
  _dt = firebaseData.cstrData();
//  Serial.print("while ext: ");
//  Serial.println(_dt);
  return _dt ;
}

void retreive_sch()
{
  int no_tag = strlen(*tag) ;
  //Serial.print("no. of tags in the DB: ");
  //Serial.println(no_tag);
  const char *_data[no_tag];

  Firebase.get(firebaseData, "/SCHEDULE DETAILS/SELECTED");
  sch_no = firebaseData.cstrData();

  Serial.print("extracting schedule");
  Serial.println(sch_no);

  strcat(base_path , sch_no); // base path w/ sch no.

  for (int i = 0 ; i < 6 ; i++)
  {
    _data[i] = fr_fbdb(tag[i]);
    Serial.print("while ext: ");
    Serial.println(_data[i]);

  }

  for(int i=0 ; i<6 ; i++)
  {
    Serial.print("after extraction:");
    Serial.println(_data[i]) ;
  }
}
```

This is the output:
```
retrieving  schedule changes -- setup
extracting schedule3
retrieving from /SCHEDULE DETAILS/SCHEDULE3/DATE
while ext: [1609612200000,\"inf\"]
retrieving from /SCHEDULE DETAILS/SCHEDULE3/FREQ FR
while ext: \"-2\"
retrieving from /SCHEDULE DETAILS/SCHEDULE3/FREQ TO
while ext: \"-2\"
retrieving from /SCHEDULE DETAILS/SCHEDULE3/WEIGHT
while ext: 29
retrieving from /SCHEDULE DETAILS/SCHEDULE3/TIME
while ext: \"6:30\"
retrieving from /SCHEDULE DETAILS/SCHEDULE3/frequency
while ext: \"-1\"
after extraction:"root":[]
after extraction:\"-1\"
after extraction:keep-alive
after extraction:\"-1\"
after extraction:"root":[]
after extraction:\"-1\"
```
As you can see, the output of the same variable ```_data[]``` inside that particular function changes.
Any idea why?

title: Any explanation for this behavior?

Answers: 1

body:
The problem is these lines of code in your function `fr_fddb()`:
```
  Firebase.get(firebaseData, full_path);
  _dt = firebaseData.cstrData();
```

You didn't share enough code to make this clear, but `firebaseData` appears to be a global which you reuse. When you call its `.cstrData()` method you're getting a pointer to the same buffer each time, and that buffer is overwritten each time you call `Firebase.get()`.

You can verify this by printing the pointer value each time through, like so in your `retrieve_sch()` function:
```
  for (int i = 0 ; i < 6 ; i++)
  {
    _data[i] = fr_fbdb(tag[i]);
    Serial.print("while ext: ");
    Serial.println(_data[i]);
    Serial.printf("_data[i] pointer %p\n", _data[i]);
  }
```

You'll likely see that the 6 pointers are identical. The value is changing because you keep reusing the same string.

The easy fix is:
```
  Firebase.get(firebaseData, full_path);
  _dt = strdup(firebaseData.cstrData());
```

This allocates memory and stores in it a duplicate of the string that was fetched from Firebase. Your function will now return that and `firebaseData` can safely be reused.

This solution will require you to free that memory at some point when you're doing using it by calling `free(_dt);` or whatever you're holding the pointer in when you're done. I leave that as an exercise for you.


body:
I wrote a piece of code that takes input from a sensor which is called the World Famous Pulse Sensor from Analogue Pin 1 and stores it in an Array with 127 elements then finds the largest in it, divides the rest by the largest, multiplies by 64 which is the maximum y length on my OLED and prints it onto the OLED.
It still gives me pre-normalized and scaled values on Serial Plotter.

What am I doing wrong?
Here is my code.

    #include <U8glib.h>
    U8GLIB_SSD1306_128X64 u8g(12, 11, 8, 9, 10);
    int x, y;int Buffer2[128];
    void pageBP();
    const int pageCount = 1;
    int p;
    void (*pages[pageCount])() = {pageBP};
    int duration [pageCount] = {1000};
    void setup() {

      u8g.setFont(u8g_font_unifont);
      u8g.setColorIndex(1);
      p = 0;
      Serial.begin(9600);

    }

    void loop() {

    u8g.firstPage();
      do {
        (*pages[p])();
      } while( u8g.nextPage() );
      delay(duration[p]);
      p = p+1;
      if (p == pageCount)
        p=0;
    }

    void pageBP() {
      for(x = 0;x < 128;x++) {
    Buffer2[x] =(analogRead(A1)>>2);//IP for PPG
    Serial.println(Buffer2[x]);
    delay(5);
    }
    for(int i = 1;i < 128; i++)
        {
           if(Buffer2[0] < Buffer2[i])
               Buffer2[0] = Buffer2[i];
        }
        for(int i = 1;i < 128; i++)
        {
           64*(Buffer2[i]/Buffer2[0]);
        }
      for(x = 0;x < 127;x++) {

    u8g.drawLine(x, Buffer2[x], x, Buffer2[x+1]); //OP to OLED for ECG

    u8g.drawLine(64, 0, 64, 63);
    u8g.drawLine(0, 32, 128, 32);}
    for(x=0;x<128;x+=8)
    u8g.drawLine(x, 31, x, 33);
    for(x=0;x<64;x+=8)
    u8g.drawLine(63, x, 65, x);
    u8g.drawFrame(0, 0, 128, 64);
    }
Here is Garbage Graph.
[![enter image description here][1]][1]

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

title: [SOLVED]Normalization not working on input buffer. How to solve this?

Answers: 1

body:
I will point out some problems with your code:

- Look at this line:

        64*(Buffer2[i]/Buffer2[0]);

    It doesn't do anything. You calculate a scaled value, but you are not saving it anywhere. You need to assign that value to a variable (like an element in a new array).

- With this code

        for(int i = 1;i < 128; i++)
        {
            if(Buffer2[0] < Buffer2[i])
                Buffer2[0] = Buffer2[i];
        }

    You are overwriting the first value in your buffer to find the highest value. That might not be a problem for you, but to be clean here, you should just use a new variable, that holds the highest value outside of the buffer.

- I'm not sure what you are trying to do with this line:

        u8g.drawLine(x, Buffer2[x], x, Buffer2[x+1]);

    Normally, you would want to draw a line from one point in the graph to the next. So the second x parameter would need to be the x value for the next point. Currently you are just drawing a vertical line. I would instead write

        u8g.drawLine(x, Buffer2[x], x+1, Buffer2[x+1]);

     since you already are only counting to 127 instead of 128.

- Even if you get the above right, the Serial Monitor would still show the unscaled values, since you are printing to Serial directly after measuring. So to display the scaled values in the Serial Monitor, you need to move the line

        Serial.println(Buffer2[x]);

    down to after the scaling, for example in the same for loop as the OLED display code.

- And finally you should really fix your indentation. That will make your code way more readable and thus better understandable. The Arduino IDE even has an autoformat feature, that you could use for that.


body:
I'm creating an Arduino library and have 3 files - a "test.ino" program, and two library/class files: "testLibrary.h" and a "testLibrary.cpp".

The library makes use of some hardware-specific resources such as registers and ISRs that depend upon which I/O pin is used, and this should be done at compile time.

I would like to *#define* a pin number in the main program which, at compile time, is used in the library to determine which code sections are activated. Since this will be a standard Arduino library for use by others, it should compile and run without users having to change their compiler or *#include* path to make it work.

But it seems that the scope of *#define* in the main program/sketch does not extend to the library.

test.ino
```
#define PIN_NUMBER 3
#include "testLibrary.h"
void setup() {}
void loop() {}
```

testLibrary.h
```
#ifndef _TESTLIBRARY_h
#define _TESTLIBRARY_h
#ifndef PIN_NUMBER
#error PIN is not defined
#endif
class test {
public:
  test();
  ~test();
};
#endif
```

testLibrary.cpp
```
#include "testLibrary.h"
test::test(){}*
test::~test(){}
```

Compiling the above branches to "#error" using the Arduino IDE 1.8.13 and also using Visual Studio with Visual Micro.

Is there a way for me to have an Arduino library use a "#define" from the main sketch?

title: Arduino IDE - scope of the pre-processor "#define"

Answers: 1

body:
The scope of a `#DEFINE` macro is the translation unit. That is the current `.c` or `.cpp` file that is currently being compiled.

In you code `PIN_NUMBER` is defined in `test.ino`. The `#include` macro literaly copies the content of `testLibrary.h` into `test.ino`. So for the compiler this is working perfectly fine as `PIN_NUMBER` is defined.

Your `testLibrary.cpp` however is not happy with that. Including `testLibrary.h` for compilation lacks the definition of `PIN_NUMBER`.

The Arduino IDE is very limited and does not offer you a way to define `PIN_NUMBER` globally. This is usually done with the compiler argument `-DPIN_NUMBER=3`. All translation units will get this argument and thus the compilation would succeed. No need to define `PIN_NUMBER` in code.


body:
Recently I custom bootloader optiboot for Arduino Uno to my custom board called Ardunesia xst X1-02, with Cortex M3 processor. I set avrdude as bootloader upload `tool = "X1-02_bootloader.upload.tool=avrdude"` in board.txt. It work normal which my board pretends to be Arduino UNO. But I want to change this log status:

```none
 Using Port                    : COM6
         Using Programmer              : arduino
         Overriding Baud Rate          : 115200
         AVR Part                      : ATmega328P
         Chip Erase delay              : 9000 us
         PAGEL                         : PD7
         BS2                           : PC2
         RESET disposition             : dedicated
         RETRY pulse                   : SCK
         serial program mode           : yes
         parallel program mode         : yes
         Timeout                       : 200
         StabDelay                     : 100
         CmdexeDelay                   : 25
         SyncLoops                     : 32
         ByteDelay                     : 0
         PollIndex                     : 3
         PollValue                     : 0x53
         Memory Detail                 :
```

I want the status log to contain my custom board instead displaying atmega328. I changed and edit file in avrdude.conf which it seems the root of this problem. I added an inheritance in Atmega328 for my custom board, but It didn't work (still displaying atmega328). I know avrdude.conf is made for avr MCU, but I wonder there is a way to add our custom/non-avr mcu to display this status log? Thank You.

**Edit**: To make it clear I want to customing _avrdude.config_ `C:\Users\yourPC\AppData\Local\Arduino15\packages\arduino\tools\avrdude\6.3.0-arduino17\etc` which its contain board ID for AVR device and I want to insert y device ID here, I inserted it on Atmega328 part parent like this:

```
part parent "m328"
    id   = "m328p";
    desc  = "ATmega328P";
    signature  = 0x1e 0x95 0x0F;

    ocdrev              = 1;
;

part parent "m328"
    id   = "m328pb";
    desc  = "ATmega328PB";     //another m328 version
    signature  = 0x1e 0x95 0x16;

    ocdrev              = 1;
;

part parent "m328"
    id   = "XST";
    desc  = "XST_X1_02";         //my board XST X1-02
    signature  = 0x1e 0x95 0x0F;

    ocdrev              = 1;
;
```

I set the signature so the bootloader recognize my board as Arduino UNO and its work well. But it keep reading as Atmega328P and not displaying XST X1-02. Should I create my own signature? any advice? Thank you

**Problem Solved!** I need to changes `compile patterns` in _platform.txt_ from `-DAtmega328_{build.board}` to `-DXST_{build.board}` which _XST_ is my MCU name. Thanks everyone!

title: How to change avrdude parameter in Arduino status log when uploading a program? avrdude.conf

Answers: 0


body:
Hi I'm making a digital fare meter, I have a problem in how my sensor reads when I'd pressed the button(single tap). I need the sensor to read once I pressed the button because when I press the button the reading starts from the beginning of the program(when the device starts) not when I pressed it. and the display is not changing if I not pressed the button i need the display in lcd to change even if i only press the button once. ( Sorry for my grammar )

```
#define sw 5 //pin at push sw is connected
#include <LiquidCrystal_I2C.h>
int irPin=A0;
int count=0;
int counter=0;
boolean state = true;
float distance1; float distance2; float distance3; float distance4;
float wait1;float wait2;float wait3;float wait4;
float fare1;float fare2;float fare3;float fare4;
float hitObject = false;

LiquidCrystal_I2C lcd1(0x26,20,4);
LiquidCrystal_I2C lcd(0x27,20,4);
int lastButtonState = HIGH;   // the previous reading from the input pin
unsigned long lastDebounceTime = 0;  // the last time the output pin was toggled
unsigned long debounceDelay = 50;    // the debounce time; increase if the output flickers
bool buttonState = HIGH; //saving state of the switch
byte tapCounter; //for saving no. of times the switch is pressed
int timediff; //for saving the time in between each press and release of the switch
bool flag1, flag2; //just two variables
long double presstime, releasetime; //for saving millis at press and millis at release
void setup() {

lcd.init();
lcd.backlight();
lcd1.init();
lcd1.backlight();
pinMode(irPin, INPUT);
lcd.setCursor(0,0); lcd.print("Seater 1  D=");
  lcd.setCursor(0,1); lcd.print("Seater 2  D=0.00");
  lcd.setCursor(0,2); lcd.print("Seater 3  D=0.00");
  lcd.setCursor(0,3); lcd.print("Seater 4  D=0.00");
  lcd1.setCursor(0,0); lcd1.print("W=       F=Php0.00");
  lcd1.setCursor(0,1); lcd1.print("W=       F=Php0.00");
  lcd1.setCursor(0,2); lcd1.print("W=       F=Php0.00");
  lcd1.setCursor(0,3); lcd1.print("W=       F=Php0.00");

  Serial.begin(9600); //for serial monitor
  pinMode(sw, INPUT_PULLUP); //setting pin 5 as input with internal pull up resistor

}

void kount()
    {
  { if (!digitalRead(irPin) && state){
 count++;
 state = false;

 }
 if (digitalRead(irPin)){
 state = true;}}}
 void compute()

{
   distance1 = count*1.73;
   fare1 = count*1.73/100+wait1;
 }
 void printlcd()

 {
 lcd.setCursor(12,0); lcd.println(distance1);lcd.println("m");

 }

void loop() {
  kount();
  compute();
  int reading = digitalRead(sw);

  if (reading != lastButtonState) {
    // reset the debouncing timer
    lastDebounceTime = millis();
  }

  if ((millis() - lastDebounceTime) > debounceDelay) {
    // whatever the reading is at, it's been there for longer than the debounce
    // delay, so take it as the actual current state:

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

  //when switch is pressed
  if (buttonState == 0 && flag2 == 0)
  {
    presstime = millis(); //time from millis fn will save to presstime variable
    flag1 = 0;
    flag2 = 1;

    tapCounter++; //tap counter will increase by 1
    //delay(10); //for avoiding debouncing of the switch
  }
  //when sw is released
  if (buttonState == 1 && flag1 == 0)
  {
    releasetime = millis(); //time from millis fn will be saved to releasetime var
    flag1 = 1;
    flag2 = 0;

    timediff = releasetime - presstime; //here we find the time gap between press and release and stored  to timediff var
    //Serial.println(timediff);
    //delay(10);
  }

  if ((millis() - presstime) > 400 && buttonState == 1) //wait for some time and if sw is in release   position
  {
    if (tapCounter == 1) //if tap counter is 1
    {
      if (timediff >= 400) //if time diff is larger than 400 then its a hold
      {
        Serial.println("Hold");
        hold(); //fn to call when the button is hold
        ;
      }
      else //if timediff is less than 400 then its a single tap
      {

        Serial.print(count);
        Serial.println("single tap");
        singleTap();

        //fn to call when the button is single taped
      }
    }
    else if (tapCounter == 2 ) //if tapcounter is 2
    {
      if (timediff >= 400) // if timediff is greater than  400 then its single tap and hold
      {
        Serial.println("single tap and hold");
        tapAndHold(); //fn to call when the button is single tap and hold
      }
      else // if timediff is less than 400 then its just double tap
      {
        Serial.println("double tap");
        doubleTap(); //fn to call when doubletap
      }
    }
    else if (tapCounter == 3) //if tapcounter is 3 //then its triple tap
    {
      Serial.println("triple tap");
      tripleTap(); //fn to call when triple tap
    }
    else if (tapCounter == 4) //if tapcounter is 4 then its 4 tap
    {
      Serial.println("four tap");
      fourTap();//fn to call when four tap
    }
    tapCounter = 0;
  }
  lastButtonState = reading;
}

void singleTap()
{
compute();
printlcd();
}
void doubleTap()
{

}
void tripleTap()
{

}
void fourTap()
{

}
void hold()
{

}
void tapAndHold()
{

}

```

title: How to make my sensor reads when i pressed the button

Answers: 0


body:
I want to blink an LED at an specific frequency, ie: 7Hz

here what Im doing

    int ledPin = 4;
    float freq = 7;

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

    float periodo() {
      float peri = 1/freq;
      float halfer = peri/2;
      float millisec = halfer*1000;
      return millisec;
      //return ((1/freq)/2)*1000;
    }

    void loop() {
      digitalWrite(ledPin, HIGH);
      delay(periodo());
      digitalWrite(ledPin, LOW);
      delay(periodo());
    }

Is this correct? is that the best way to do it?

thanks in advance!

title: confirming this will blink LED at given frequency

Answers: 1

body:
You can check if it is correct by timing it for one minute and check if it is (approximately) ok.

However, I see a few improvements:

- First is that you always return 1/7/2*1000 = 71.429, which is rounded down to 71. 71 * 14 = 994 ms so you get a bit faster speed than 7 Hz. if this is a problem you have to compensate for this.
- Another small problem is that you `delay`, but the `digitalWrite` commands also take some time which is not included for the delays. So you need also to take this into account when using a precise delay.
- When using floats I always use float constant numbers, like 1.0 and 7.0 instead of 1 and 7. This can especially be useful when you divide two integers (e.g. 1/7), which results in 0.14 this is rounded down to 0 as it is an int.

The best you can do is using the `millis` command. You keep a timer and compare it to the current `millis` value. If it is too high, do a state change. This will take into account every other method you do meanwhile the `digitalWrite`s.

Something like: (code fixed due to EdgarBonet's remarks)

    const float FREQ = 7.0; // Hz
    const int PIN_NR = 4;

    unsigned long _startTime;
    unsigned long _counter;

    int _currentState = LOW;

    void setup()
    {
      _startTime = millis();
      _counter = 0;
      _currentState = LOW;
      digitalWrite(PIN_NR, _currentState);
    }

    void loop()
    {
      if (_startTime + _counter * 1000.0 / FREQ / 2.0 >= millis())
      {
        _counter++;
        _currentState = ~_currentState;
        digitalWrite(PIN_NR, _currentState);
      }
    }

Some small notes:

- _currentState is the current state of the LED, with ~ you can flip it (it's called the `not` operator).
- _startTime is the (close to zero) value of the `millis` value at startup.
- Take in mind there is a limit how long this app can run or precise. `millis` works with ms, meaning you cannot get beyond 500 Hz, and you get 'approximations' with frequencies below in some cases. E.g. when Freq = 80 Hz, you get 1000 * 1 / 80 / 2 = 1000 / 160 = 6.25 => 6, which is actually 1000/6/2=83.3 Hz.
- Also the counter is added once per state change, and because of 1000 * _counter ... an overflow exists when _counter >= 256 * 256 * 256 * 256 / 1000 = about 4 million. With 1000 state changes per second, this happens after 4000 seconds, which is 66 minutes. For 7 Hz it will not occur fast.


body:
Arduino: 1.8.3 (Windows 7), Board: "Arduino/Genuino Uno"

    Sketch uses 1094 bytes (3%) of program storage space. Maximum is 32256 bytes.
    Global variables use 9 bytes (0%) of dynamic memory, leaving 2039 bytes for local variables. Maximum is 2048 bytes.
    C:\Program Files (x86)\Arduino\hardware\tools\avr/bin/avrdude -CC:\Program Files (x86)\Arduino\hardware\tools\avr/etc/avrdude.conf -v -patmega328p -carduino -PCOM14 -b115200 -D -Uflash:w:C:\Users\Admin\AppData\Local\Temp\arduino_build_360380/FINALROTARO.ino.hex:i

    avrdude: Version 6.3, compiled on Jan 17 2017 at 12:00:53
             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                    : COM14
             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=0x1f
    avrdude: stk500_recv(): programmer is not responding
    avrdude: stk500_getsync() attempt 2 of 10: not in sync: resp=0x1f
    avrdude: stk500_recv(): programmer is not responding
    avrdude: stk500_getsync() attempt 3 of 10: not in sync: resp=0x1f
    avrdude: stk500_recv(): programmer is not responding
    avrdude: stk500_getsync() attempt 4 of 10: not in sync: resp=0x1f
    avrdude: stk500_recv(): programmer is not responding
    avrdude: stk500_getsync() attempt 5 of 10: not in sync: resp=0x1f
    avrdude: stk500_recv(): programmer is not responding
    avrdude: stk500_getsync() attempt 6 of 10: not in sync: resp=0x1f
    avrdude: stk500_recv(): programmer is not responding
    avrdude: stk500_getsync() attempt 7 of 10: not in sync: resp=0x1f
    avrdude: stk500_recv(): programmer is not responding
    avrdude: stk500_getsync() attempt 8 of 10: not in sync: resp=0x1f
    avrdude: stk500_recv(): programmer is not responding
    avrdude: stk500_getsync() attempt 9 of 10: not in sync: resp=0x1f
    avrdude: stk500_recv(): programmer is not responding
    avrdude: stk500_getsync() attempt 10 of 10: not in sync: resp=0x1f

    avrdude done.  Thank you.

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

    This report would have more information with
    "Show verbose output during compilation"
    option enabled in File -> Preferences.

title: Can't upload programme on arduino uno

Answers: 0


body:
I'm using a Pro-Micro to send messages using NRF24 module from a remote location, using batteries (later on, will be recharged using solar panel).

To conserve power, Pro-Micro wakes up every 30 minutes, sends its data. My goal is to power up NRF24 module only when needed, in order to conserve power as much as possible.

For that I tried 3 ways:

1) Using a Relay to cut off `5V` input to the NRF24 module.

2) Using a MOSFET `FQP30N06 `, connected to `GND` of NRF24 module.

3) Using NRF24's `powerDown()` function reduce consumption.

**These are the current draw results:**

a) During sleep, power consumption of Pro-Micro only is 3.4 mA ( due to LED remains ON ).

b) Pro-Micro + NRF24 module, both normal operation ~70mA.

c) Using a relay + entering Pro-Micro to Sleep mode: 6mA.

d) Using `powerDown()` + entering Pro-Micro to Sleep mode: 30mA.

e) Using a MOSFET + entering Pro-Micro to Sleep mode: **180mA.** (yes, MOSFET turns off power to NRF24 ).

**Questions:**

** I have to say that my first go was for using a MOSFET, but I was amazed by the result! What is the reason for that? Can it be the when MOSFET in its OFF state consumes so much power ?

** I would like to hear from other's experience for better ways to do such.

Guy

title: Power down NRF24 to conserve battery life using MOSFET

Answers: 0


body:
I can't find any tutorials online explaining how to wire and control a 16mm push button like the one in the picture:

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

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

Do  you have any suggestions as to how use it with an arduino or a raspberry pi?

title: How to wire and control a 16mm button with 2 legs using arduino?

Answers: 1

body:
A pushbutton is a pushbutton. It is a momentary switch. Since it has flexible wires, and needs a place to mount, you should probably wire it using a breadboard.

That pushbutton looks like a panel mount pushbutton. You might want to mount it in a pice of plastic or sheet metal. (Unscrew that nut up by the red part that you press. Measure the outside diameter of the threaded part. Drill a hole ≈1/64" (≈0.4MM) bigger than the switch diameter into the plastic/metal. Insert the pushbutton from underneath the panel. screw the nut back on to secure it. Tighten moderately tight with needle-nose pliers, being careful not to round off the corners of the nut.

To wire it:

Get a breadboard. Run wires from your Arduino to the breadboard.

Wire the pushbutton into the breadboard as well.

There are various libraries that offer switch debouncing, or you can write your own fairly easily.

I suggest using INPUT_PULLUP mode, and wiring your switch between an Arduino digital input and ground. When the switch is open, the input will read HIGH. When you press the the switch, the input will drop to LOW.

If you want to debounce the switch input yourself: When the switch changes state, note the value of `millis()`, and ignore any new changes for a brief period (try 20-100 mS).


body:
What I want to do:
I have 7 touch buttons on my board (ESP32 TTGO T-Display) and I want to attach interrupts to everyone, calling the same function.
In this function I would like to use touch_pad_get_status() or other to get which button was touched. Then a switch case would do the rest.

What I'm facing:
This code

      Serial.print("Button ");
      uint32_t touch = touch_pad_get_status();
      Serial.println(String(touch));

always returns 0, no matter what.

What I've tried:
Including this part of code to the setup

      touch_pad_init();
      touch_pad_set_fsm_mode(TOUCH_FSM_MODE_TIMER); //tried the SW MODE too
      touch_pad_io_init(TOUCH_PAD_GPIO15_CHANNEL);

But nothing seem to work. I don't want to make 7 different functions...

Thanks in advance.

title: What is touch_pad_get_status() supposed to return?

Answers: 1

body:
As pointed out from people in the comments, things need to be different.
If you use the function `touchAttachInterrupt`, things are a bit simpler.
The example that comes with the ESP32 library is enough to make you understand.

If you want to do what I did, this is how:

      touch_pad_init();
      touch_pad_set_fsm_mode(TOUCH_FSM_MODE_TIMER);
      touch_pad_config(TOUCH_PAD_GPIO2_CHANNEL, 500);
      touch_pad_config(TOUCH_PAD_GPIO15_CHANNEL, 500);
      touch_pad_config(TOUCH_PAD_GPIO13_CHANNEL, 500);
      touch_pad_isr_register(TouchButton, NULL);
      touch_pad_intr_enable();

Put this code in the `setup()`. Of course needs the `init()`, but also needs to be set to timer mode, or otherwise you're going to need to `start()` probably.
The `config()` is to configure the pin as an interrupt. I've set 500 in the threshold because the readings of `touch_pad_read()` told me it went from 800 untouched to 50 touched, so the midterm I chose 500.
`isr_register` is the function that tells to call `TouchButton()`, with `NULL` as argument to it.

    void TouchButton(void *arg)
    {
      uint32_t touch = touch_pad_get_status();
      touch_pad_clear_status();
      Serial.print("Button ");
      Serial.println(String(touch));
    }

This is the declaration of the callback function I've done. It should be noted that `clear_status()` should be called as soon as possible after the `get_status()`, preventing the system from panicking (that's the name). You'll also see in the serial monitor that each button represents a power of 2. That's because the `get_status()` returns the pin mask in binary. So just do something similar to this

    for (int i = 0; i < TOUCH_PAD_MAX; i++) {
        if ((pad_intr >> i) & 0x01) {
            s_pad_activated[i] = true;
        }
    }

and you'll get a vector of which one was pressed.


body:
I am attempting to create a simple code that will home the motor then wait for input for direction.  I have the homing function working, however the loop that reads the data from the serial monitor and returns it to the program is acting really buggy.  If I enter a 1 the stepper will rotate one turn in the CCW direction, hit the home mark then reverse and go CW.  If I enter a 0 the stepper will make one turn in the CW direction then repeat that move.  I added a bit of feedback so I could see what my direction variable is doing, it will hold a "1", make the move, rehome and show a "0".  I know the problem is in the loop, but for the life of me I can't seem to figure it out.  I am new to coding, so for the love of god, go easy on me!  I have added my full code so someone a little higher up in the coding world will see what I am doing.  This is just some code so I can try and learn a little something and make some strange stuff in the future.  Gotta start somewhere.  If this question is better asked on a different thread, please direct me to it.

```
    // Connections
#define HALL_SENSOR      3
#define DIR      10
#define STEP      11

void homefunction() {

  while (digitalRead(HALL_SENSOR) == 1) {

    digitalWrite(DIR, LOW);
    digitalWrite(STEP, HIGH);
    delayMicroseconds(4000);
    digitalWrite(STEP, LOW);
    delayMicroseconds(4000);
  }

}

void setup() {

  // Setup the stepper controller pins as Outputs
  pinMode(DIR, OUTPUT);
  pinMode(STEP, OUTPUT);

  // Setup the Hall Effect switch as an Input
  pinMode(HALL_SENSOR, INPUT_PULLUP);

  // Home the motor
  homefunction();

  // Sets up serial monitor
  Serial.begin(9600);

}

void loop()

  {int Direction; //Use to get the direction from the serial monitor
    Serial.println("What Direction would you like the motor to spin?"); //Input data
    while (Serial.available() == 0) //Wait for data
    Serial.read();
       Direction = Serial.parseInt();

 {
  // Read motor direction
  digitalWrite(DIR, Direction);
  Serial.println(Direction);

  // Spin motor
  for(int x = 0; x < 200; x++)
  {
    // while (Direction==0) //Added to hold value
    digitalWrite(STEP, HIGH);
    delayMicroseconds(4000);
    digitalWrite(STEP, LOW);
    delayMicroseconds(4000);
    //Serial.println(x);
  }}}
```

title: Input from serial monitor to control stepper direction coding problem

Answers: 0


body:
I have a Arduinio nano and a ATMEGA168. I'm using the ST7789 library. The sample code which comes with the library runs perfectly and runs the display when using the Nano, but the same code does nothing on the ATMEGA168. I'm using the official pin mappings, so I sure it isn't the pins. Any suggestions I could try, or will a ATMEAG168 not drive a TFT?
EDIT:
I'm using the library written for adafruit.
```
#include <Adafruit_GFX.h>    // Core graphics library
#include <Adafruit_ST7789.h> // Hardware-specific library for ST7789
#include <SPI.h>             // Arduino SPI library
```
[![enter image description here][1]][1]

on the nano I'm using:
- D13 -> SCL
- D11 -> SDA
- D9 -> DC
- D8 -> RES

on the ATmega:
- 19 (PB5) -> SCL
- 17 (PB3)-> SDA
- 15 (PB1)-> DC
- 14 (PB0)-> RES

ANSWER TO COMMENTS:
Yes I mean the exact same code without changing the pin numbers. The pin numbers I use on the ATmega are just the same pins connected via the official atmega mapping here: [https://www.arduino.cc/en/Hacking/PinMapping168][2]

Yes the ATMega is running, I've used a logic probe on the output pins and there is output on the pin. I've run numerous other programs more sophisticated than blinking LED's and the chips are fine. The clock source is PB0 (pin 14) of the atmega. Reference pinouts in the above link.

I'm not using AC power, high frequencies, or switching subcircuits, so I didn't believe I needed any decoupling. Why do you believe there should be, and where do you believe they should be located?

EDIT: MORE INFO FOR COMMENTORS:
I'm just trying to use the terminology written on the PCB. :)
This is the best I can do and stay under the 2 meg limit for images.

EDIT 3:

Yes, I thought the same and swapped the screens. I also tried swapping all the wires, just in case, and moving everything to a different breadboard and power supply. In addition, I swapped out the atmega since I have a couple of them. It is perplexing.

[![enter image description here][3]][3]

```
/*
 * Interfacing Arduino with ST7789 TFT display (240x240 pixel).
 * Graphics test example.
 * This is a free software with NO WARRANTY.
 * https://simple-circuit.com/
 */
/**************************************************************************
  This is a library for several Adafruit displays based on ST77* drivers.

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

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

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

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

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

// ST7789 TFT module connections
#define TFT_CS    10  // define chip select pin
#define TFT_DC     9  // define data/command pin
#define TFT_RST    8  // define reset pin, or set to -1 and connect to Arduino RESET pin

// Initialize Adafruit ST7789 TFT library
Adafruit_ST7789 tft = Adafruit_ST7789(TFT_CS, TFT_DC, TFT_RST);

float p = 3.1415926;

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

  // if the display has CS pin try with SPI_MODE0
  tft.init(240, 240, SPI_MODE2);    // Init ST7789 display 240x240 pixel

  // if the screen is flipped, remove this command
  tft.setRotation(2);

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

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

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

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

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

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

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

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

  testdrawrects(ST77XX_GREEN);
  delay(500);

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

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

  testroundrects();
  delay(500);

  testtriangles();
  delay(500);

  mediabuttons();
  delay(500);

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

  [1]: https://i.stack.imgur.com/UpL0F.png
  [2]: https://www.arduino.cc/en/Hacking/PinMapping168
  [3]: https://i.stack.imgur.com/dxhYG.jpg

title: TFT Screen & ATMEGA168

Answers: 0


body:
I have this callback function in my Firmata sketch. It receives a string as a character array and does something with it. The problem is, that the string is being sent to the Arduino in `T\0h\0i\0s\0` form - after each character there is a `\0` terminator. As you can see, my function is switching the d13 LED on if the string incoming is `COMMAND`. I had tried to use several comparison methods:
- `strcmp(myString, "COMMAND") == 1`;
- `myString == "COMMAND"`;
- `strcmp(myString, "COMMAND\0") == 1`;
- `myString == "COMMAND\0"`;
- `strcmp(myString, "C\0O\0M\0 M\0A\0N\0D\0") == 1`;
- `myString == "C\0O\0M\0 M\0A\0N\0D\0"`;
- `==` with saving the `COMMAND` to a char array variable;
- `strcmp` with saving the `COMMAND` to a char array variable;
- last two things with converting both the incoming and the needed to a String instance;
- comparing a String instance with a directly stated `"COMMAND"`...

Nothing works. How can I compare the strings workably?

Full Arduino sketch:
```c++
#include <Firmata.h>

void stringCallback(char *myString)
{
  if (strcmp(myString, "COMMAND") == 1) {
    digitalWrite(13, HIGH);
  }
  Firmata.sendString(myString);
}

void sysexCallback(byte command, byte argc, byte *argv)
{
  Firmata.sendSysex(command, argc, argv);
}

void setup()
{
  Firmata.setFirmwareVersion(FIRMATA_FIRMWARE_MAJOR_VERSION, FIRMATA_FIRMWARE_MINOR_VERSION);
  Firmata.attach(STRING_DATA, stringCallback);
  Firmata.attach(START_SYSEX, sysexCallback);
  Firmata.begin(57600);
  pinMode(13, INPUT);
}

void loop()
{
  while (Firmata.available()) {
    Firmata.processInput();
  }
}
```

Full code of the desktop program:
```python
import pyfirmata, time

class CustomArduino(pyfirmata.Arduino):
    def __init__(self, port: str):
        pyfirmata.Arduino.__init__(self, port)
        self.iterator = pyfirmata.util.Iterator(self)
        self.iterator.start()

        self.add_cmd_handler(0x71, self.receiveString)

    def receiveString(self, *args, **kwargs):
        print(f'Raw: {args}\n'
              f'Received: {pyfirmata.util.two_byte_iter_to_str(args)}')

    def sendString(self, data):
        self.send_sysex(0x71, pyfirmata.util.str_to_two_byte_iter(data))

    def send_sysex(self, sysex_cmd, data=[]):
        """
        Sends a SysEx msg.
        :arg sysex_cmd: A sysex command byte
        : arg data: a bytearray of 7-bit bytes of arbitrary data
        """
        msg = bytearray([pyfirmata.pyfirmata.START_SYSEX, sysex_cmd])
        msg.extend(data)
        msg.append(pyfirmata.pyfirmata.END_SYSEX)
        self.sp.write(msg)

print('STRING TESTER\nPlease input your COM port: ', end = '')
myCom = str(input())
device = CustomArduino(myCom)

while True:
    device.sendString(input('Send: '))
    time.sleep(1)
```

Strange detail: my Arduino is on the `COM6` COM-port. If I connect it via my program and send `com6` to the arduino, the D13 LED turns on!

title: String comparison problem

Answers: 1

body:
As @timemage stated, `strcmp` returns `0` for equal. Sincerely in the provided code, while you send a message, which contents are **not** `COMMAND`, the LED will be turned on.

To get what we need, we must compare `strcmp` return value with `0`! If it equals, then the strings match, and your suggested code is being executed:

```c++
void stringCallback(char *myString)
{
  if (strcmp(myString, "COMMAND") == 0) {
    digitalWrite(13, HIGH);
  }
  Firmata.sendString(myString);
}
```


body:
I have written a small test code for Arduino Uno which is as follows:

    unsigned char tes[4];
    char testing[4];

    void setup() {
        Serial.begin(9600);
        for (int i = 0; i < 4; i++) {
            testing[i] = i;
            tes[i] = i;
        }
        for (int i = 0; i < 4; i++) {
            Serial.print("unsigned char is: ");
            Serial.println(tes[i]);
            Serial.print("char is: ");
            Serial.println(testing[i]);
        }
    }

    void loop() {
    }

and the output which I get is as follows

    unsigned char is: 0
    char is:
    unsigned char is: 1
    char is:
    unsigned char is: 2
    char is:
    unsigned char is: 3
    char is:

Can someone help me out why is the difference in output.

title: Difference between char array and unsigned char array

Answers: 2

body:
An unsigned char is treated as a number, and a signed char as a character.
See the https://simple.wikipedia.org/wiki/ASCII table for the result.

body:
***tl;dr : Since unsigned char is represented as a byte value, the output to the serial is the byte representation, not the char***

I re-wrote the code you had for reference:

    #define CHARS 255
    #define BAUD 115200

    unsigned char unsChar[CHARS];
    char sinChar[CHARS];

    void setup() {
      Serial.begin(BAUD);
      Serial.println("~~Setup~~");
      for(int i = 0; i < CHARS; i++) {
        unsChar[i] = (unsigned char)i;
        sinChar[i] = (char)i;
      }
    }

    void loop() {
      Serial.println("~~Loop~~");
      for(int i = 0; i < CHARS; i++) {
        Serial.print("INDEX        : ");
        Serial.println(i);
        Serial.print("unsigned char: ");
        Serial.println(unsChar[i]);
        Serial.print("         char: ");
        Serial.println(sinChar[i]);
        Serial.println("---------------------");
      }
      delay(10000);
    }

When you run this you'll see the [`unsigned char`][1] is simply printed to the serial like any other `byte` value but the [`char`][2] value is printed as a character according to the [ASCII chart][3].

If you compare the documentation for [`unsigned char`][1]

> **An unsigned data type that occupies 1 byte of memory**. Same as the byte datatype.

The unsigned char datatype encodes numbers from 0 to 255.

For consistency of Arduino programming style, the byte data type is to be preferred.

versus a normal (signed) [`char`][2]:

> A data type used to store a character value. Character literals are written in single quotes, like this: 'A' (for multiple characters - strings - use double quotes: "ABC").

Characters are stored as numbers however. You can see the specific encoding in the [ASCII chart][3]. This means that it is possible to do arithmetic on characters, in which the ASCII value of the character is used (e.g. 'A' + 1 has the value 66, since the ASCII value of the capital letter A is 65). See [`Serial.println`][4] reference for more on how characters are translated to numbers.

**The size of the char datatype is at least 8 bits.** It’s recommended to only use char for storing characters. For an unsigned, one-byte (8 bit) data type, use the byte data type.

So size wise an array of chars and unsigned chars are going to be the same. It's more about the representation of the underlying number (byte) and what works best for your use case.

  [1]: https://www.arduino.cc/reference/en/language/variables/data-types/unsignedchar/
  [2]: https://www.arduino.cc/reference/en/language/variables/data-types/char/
  [3]: https://www.arduino.cc/en/Reference/ASCIIchart
  [4]: https://www.arduino.cc/reference/en/language/functions/communication/serial/println


body:
I am trying to decode IR codes of my Samsung tv remote

But the receiver always receiving "0"

Schematics:

[![Schematics][1]][1]

Code:
```
#include <IRremote.h>

int RECV_PIN = 11;
IRrecv irrecv(RECV_PIN);
decode_results results;

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

void loop()
{
  if (irrecv.decode(&results))
    {
    int value = results.value;
    Serial.println(" ");
    Serial.print("Code: ");
    Serial.println(results.value);
    Serial.println(" ");
    irrecv.resume();
    Serial.println("*****************");
    }
}
```

Please help me to decode my IR codes

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

title: IR receiver receives only 0

Answers: 1

body:
Next update with [3.1 of the library][1], you need to call `irrecv.decodedIRData.decodedRawData` to get the data. This code worked for me:

    #include <IRremote.h>

    int IRpin = 11;
    IRrecv irrecv(IRpin);

    void setup()
    {
      Serial.begin(9600);
      irrecv.enableIRIn(); // Start the receiver
    }

    void loop()
    {
      if (irrecv.decode())
        {
          Serial.println(irrecv.decodedIRData.decodedRawData); // Print the Serial
          irrecv.resume();   // Receive the next value
        }
    }

  [1]: https://github.com/Arduino-IRremote/Arduino-IRremote#converting-your-2x-program-to-the-3x-version


body:
I would like to ask you how I can generate a `dot_a` file for a given library for ESP32? I want to replace my .cpp file with a precompiled `.a` in the Arduino IDE.
Is that possible? Can you please guide me?

title: generate and using a precompiled library ESP32

Answers: 0


body:
Here is my code I am collecting data using an ECG sensor and trying to enhance the incoming data by stretching it across the x axis. Which results in this.
[![enter image description here][1]][1]

  [1]: https://i.stack.imgur.com/jqY7T.jpg
After this the screen eventually just goes black. What am I doing wrong?
 This is my code.

    #include <U8glib.h>
    U8GLIB_SSD1306_128X64 u8g(12, 11, 8, 9, 10);
    int Buffer[128];int Buffer2[128];int max=0;
    //int largest;
    void pageECG();     // Page-1

    const int pageCount = 2;
    int p;
    void (*pages[pageCount])() = {pageECG};
    int duration [pageCount] = {10000};
    void setup() {

      u8g.setFont(u8g_font_unifont);
      u8g.setColorIndex(1);
      p = 0;
      Serial.begin(9600);

    }

    void loop()
    {
    u8g.firstPage();
      do {
        (*pages[p])();
      } while( u8g.nextPage() );
      delay(duration[p]);
      p = p+1;
      if (p == pageCount)
        p=0;
    }
    void pageECG() {
    for(int x = 0;x < 128;x++)
    {
    Buffer[x] =(analogRead(A0)*0.075);//This loop takes data input
    delay(5);
    if(Buffer[x]<32&&Buffer[x]!=2)
    x-=2;
    if(Buffer[x]>32&&Buffer[x]!=62)
    x+=2;
    Serial.println(Buffer[x]);
    }

    for(int x = 0;x < 127;x++)
    {
    u8g.setFont(u8g_font_unifont);
    u8g.drawStr( 0, 60, "ECG");
    u8g.drawLine(x, Buffer[x], x,Buffer[x+1]); //OP to OLED for BP

    }}

title: SSD1306 unable to display Text and waveform cohesively.Why?

Answers: 1

body:
Well, one problem is this: You have made an array of pointer to function, but only initialized the first of the two, to `pageECG`.

```c++
const int pageCount = 2;
int p;
void (*pages[pageCount])() = {pageECG};
```

The last line there roughly equivalent to:

```c++
void (*pages[pageCount])() = {pageECG, nullptr};
```

Later in `loop()` you have:

```c++
  u8g.firstPage();
  do {
    (*pages[p])();
  } while( u8g.nextPage() );
  delay(duration[p]);
  p = p+1;
  if (p == pageCount)
    p=0;
```

After the first execution of `loop()`, `p` is 1.  Since it was not 2, it was not reset by your `if (p == pageCount) p=0;`  So on the next pass through `loop()`, `(*pages[p])();` is     `(*pages[1])();`  where `pages[1]` is `nullptr`.

In practice, what you're doing is generating and executing an AVR `icall` (indirect call) instruction to address 0x0000 (`nullptr` representation) to the reset vector.  So, your sketch starts over almost like a reset, except the hardware has not been reset.  Importantly, the interrupts are still configured as they were and the global interrupt flag is on, which means all manner of potential weirdness if one of them manages to execute before you get back ground `setup().`  So, it's difficult to say exactly why you're seeing what you're seeing.  But, it doesn't surprise me as a potential outcome.  And it may not be the *only* problem; just *a* problem.


body: I can set pin mode to input or output through the DDRx registers. How can I enable the internal pullup resister through a register?

title: Configure input pullup through registers

Answers: 1

body:
Credits to GoForSmoke.
Also see Gerben's comment below.

See: https://forum.arduino.cc/index.php?topic=286145.0

    byte ddrcMask =       ~
    (
            (1 << DDC0) |  // pinMode( 14, INPUT ); // Set to input
            (1 << DDC1) |  // pinMode( 15, INPUT ); // Set to input
            (1 << DDC2) |  // pinMode( 16, INPUT ); // Set to input
            (1 << DDC3)    // pinMode( 17, INPUT ); // Set to input
    );

    byte portcMask =
    (
            (1 << PORTC0) |  // digitalWrite( 14, HIGH ); // Enable the pullup
            (1 << PORTC1) |  // digitalWrite( 15, HIGH ); // Enable the pullup
            (1 << PORTC2) |  // digitalWrite( 16, HIGH ); // Enable the pullup
            (1 << PORTC3)    // digitalWrite( 17, HIGH ); // Enable the pullup
    );

    byte pincMask = ( (1 << PINC0) | (1 << PINC1) | (1 << PINC2) | (1 << PINC3) );

    void setup( void )
    {
      // Configure the pins for input
      DDRC = DDRC & ddrcMask;

      // Enable the pullups
      PORTC = PORTC | portcMask;

      // Read all four inputs
      uint8_t Pdat = PINC & pincMask;
    }

    void loop( void )
    {
    }


body:
I'm trying to interface an Arduino Mega with an [AD7714][1] ADC. This ADC requires a command to be sent to the communications register (in my case 0x5C) in order to begin a read from the data register.

My question is how do I receive the data that is transmitted from the Slave ADC to the Master Arduino on the MISO line?

At the moment I have this code in an interrupt that is activated when the DRDY goes low:

```c++
byte dataIn;
byte dataOut = 0;
adc_write_reg(0x5C); //tell ADC to read data from data register
dataIn = SPI.transfer(dataOut); //transmit data in order to recieve data??
```

Thanks!

  [1]: https://www.analog.com/en/products/ad7714.html

title: Arduino Master SPI MISO Receive Data

Answers: 0


body:
I'm a newbie in using the **Arduino Ethernet Shield v2** (Arduino product code [A000024][1]) and I'm experiencing some strange behaviours on a critical work with strict deadline.

The project involve some Arduino (both UNOs and MEGA2560s) sending sensor data via OSC to a couple of destination PCs for later processing.

To do that I'm using what it seemed to me to be a quite simple to use Arduino OSC library, the [CNMAT one][2].

I've noticed this fact, which I think is related to some hardware malfunction.

I've found my code getting stuck even with a correct setup of the LAN. The code stops working, stops sending OSC messages, Ethernet shield is no more reachable with the *ping*. This persists also after loading again the code, or manually resetting the Arduino board. Initially I thought it was my fault but I've found that, substituting the shield with another one, the problem magically disappeared. On one of the problematic shield I've also experienced many continuous shutdowns and startups of the Arduino every 5 seconds (firmware restart from the setup)!

Are these ethernet shields known to be defective or having some issues?
The strange thing is that I've experienced this problem on 3 out of 8 of them: this is super critical!
Have you experienced something similar? Do you know of similar problems occurred before?

---

For debug purposes, here's a code test I've written and tried on a single Arduino UNO, always the same, using the same LAN setup (ethernet cable, IP addresses, Ethernet switch) switching two different Ethernet shields:

```c++
/* NET stuff ********************************************/
#include <SPI.h>
#include <Ethernet.h>
#include <EthernetUdp.h>
EthernetUDP Udp;

IPAddress ip(10, 3, 3, 210); // the Arduino's IP
byte mac[] = { 0xA8, 0x61, 0x0A, 0xAE, 0x83, 0xCE };

#define DELAY 1000

// SETUP //////////////////////////////////////////////////////////////////
void setup() {

  Serial.begin( 115200 );
  Serial.println("setup");

  // Ethernet and OSC utilities **************************
  Ethernet.begin(mac, ip);

  // Hardware status check
  if (Ethernet.hardwareStatus() == EthernetNoHardware) {
    Serial.println("Ethernet shield was not found.");
  }
  else if (Ethernet.hardwareStatus() == EthernetW5100) {
    Serial.println("W5100 Ethernet controller detected.");
  }
  else if (Ethernet.hardwareStatus() == EthernetW5200) {
    Serial.println("W5200 Ethernet controller detected.");
  }
  else if (Ethernet.hardwareStatus() == EthernetW5500) {
    Serial.println("W5500 Ethernet controller detected.");
  }

  //Tells you whether the link is active.
  // LinkOFF could indicate the Ethernet cable is unplugged or defective.
  if (Ethernet.linkStatus() == Unknown) {
    Serial.println("Link status unknown. Link status detection is only available with W5200 and W5500.");
  }
  else if (Ethernet.linkStatus() == LinkON) {
    Serial.println("Link status: On");
  }
  else if (Ethernet.linkStatus() == LinkOFF) {
    Serial.println("Link status: Off");
  }

  while( Ethernet.linkStatus() == LinkOFF ) {
    delay( DELAY );
  }
}

// LOOP ///////////////////////////////////////////////////////////////////
void loop()
{

  if (Ethernet.linkStatus() == LinkOFF) {
    Serial.print("Ethernet link broken!\t");
    Serial.println("please connect the Ethernet cable");
    delay( DELAY );
    return;
  }

  Serial.println("LOOP working as expected!");
  delay( DELAY );
}
```

When I try this code using the "defective" Arduino Ethernet shield the Serial monitor print something like this (note that I'm not doing anything, I'm leaving everything untouched):

    [...]
    14:25:17.906 -> setup
    14:25:18.471 -> W5500 Ethernet controller detected.
    14:25:18.471 -> Link status: On
    [...]
    14:26:41.545 -> LOOP working as expected!
    14:26:42.542 -> LOOP working as expected!
    14:26:43.538 -> LOOP working as expected!
    14:26:44.535 -> Ethernet link broken! please connect the Ethernet cable
    14:26:45.531 -> LOOP working as expected!
    14:26:46.561 -> LOOP working as expected!
    14:26:47.558 -> LOOP working as expected!
    14:26:48.555 -> LOOP working as expected!
    14:26:49.552 -> Ethernet link broken! please connect the Ethernet cable
    14:26:50.549 -> LOOP working as expected!
    14:26:51.546 -> LOOP working as expected!
    14:26:52.543 -> LOOP working as expected!
    14:26:53.540 -> LOOP working as expected!
    14:26:54.570 -> LOOP working as expected!
    14:26:55.567 -> Ethernet link broken! please connect the Ethernet cable
    14:26:56.564 -> LOOP working as expected!
    14:26:57.561 -> LOOP working as expected!
    14:26:58.557 -> LOOP working as expected!
    14:26:59.553 -> Ethernet link broken! please connect the Ethernet cable
    14:27:00.550 -> Ethernet link broken! please connect the Ethernet cable
    14:27:01.546 -> LOOP working as expected!
    14:27:02.576 -> Ethernet link broken! please connect the Ethernet cable
    14:27:03.572 -> LOOP working as expected!
    14:27:04.569 -> LOOP working as expected!
    14:27:05.566 -> LOOP working as expected!
    14:27:06.563 -> LOOP working as expected!
    14:27:07.560 -> LOOP working as expected!
    14:27:08.557 -> LOOP working as expected!
    14:27:09.587 -> LOOP working as expected!
    14:27:10.583 -> Ethernet link broken! please connect the Ethernet cable
    14:27:11.580 -> LOOP working as expected!
    14:27:12.577 -> LOOP working as expected!
    [...]

In the meantime, the ping stops working and will not work again until I reboot the Arduino:

    [...]
    64 bytes from 10.3.3.210: icmp_seq=301 ttl=128 time=0.185 ms
    64 bytes from 10.3.3.210: icmp_seq=302 ttl=128 time=0.171 ms
    64 bytes from 10.3.3.210: icmp_seq=303 ttl=128 time=0.184 ms
    64 bytes from 10.3.3.210: icmp_seq=304 ttl=128 time=0.229 ms
    64 bytes from 10.3.3.210: icmp_seq=305 ttl=128 time=0.206 ms
    64 bytes from 10.3.3.210: icmp_seq=306 ttl=128 time=0.278 ms
    64 bytes from 10.3.3.210: icmp_seq=307 ttl=128 time=0.143 ms
    64 bytes from 10.3.3.210: icmp_seq=308 ttl=128 time=0.229 ms
    64 bytes from 10.3.3.210: icmp_seq=309 ttl=128 time=0.198 ms
    From 10.3.3.165 icmp_seq=335 Destination Host Unreachable
    From 10.3.3.165 icmp_seq=336 Destination Host Unreachable
    From 10.3.3.165 icmp_seq=339 Destination Host Unreachable
    From 10.3.3.165 icmp_seq=342 Destination Host Unreachable
    From 10.3.3.165 icmp_seq=343 Destination Host Unreachable
    From 10.3.3.165 icmp_seq=344 Destination Host Unreachable
    [...]

As you see the "Link" seems to be on and than off repeatedly. I don't know why from the moment. I'm not modifying anything on my network setup (the LAN cable or anything like that).

I don't know why the ping stops working and will not work again even if the Serial monitor is telling the LINK is ON.

Let me know as soon as you can and thank you so much for your help and support.

bests

na

PS: I've posted a similar question on the Arduino forum but I had no way of understanding what kind of problem is this --> [link][3]

  [1]: https://store.arduino.cc/usa/arduino-ethernet-shield-2
  [2]: https://github.com/CNMAT/OSC
  [3]: https://forum.arduino.cc/index.php?topic=725989.msg4882309#msg4882309

**edit 11/02/2021**

I've written a new code sketch to always print the status of the link. Here it is.

```c++
    /* NET stuff ********************************************/
    #include <SPI.h>
    #include <Ethernet.h>
    #include <EthernetUdp.h>
    EthernetUDP Udp;

    IPAddress ip(10, 3, 3, 210); // the Arduino's IP
    byte mac[] = { 0xA8, 0x61, 0x0A, 0xAE, 0x83, 0xD5 };

    #define DELAY 1000

    // SETUP //////////////////////////////////////////////////////////////////
    void setup() {

      Serial.begin( 115200 );
      Serial.println("setup");

      // Ethernet and OSC utilities **************************
      Ethernet.begin(mac, ip);

      // Hardware status check
      if (Ethernet.hardwareStatus() == EthernetNoHardware) {
        Serial.println("Ethernet shield was not found.");
      }
      else if (Ethernet.hardwareStatus() == EthernetW5100) {
        Serial.println("W5100 Ethernet controller detected.");
      }
      else if (Ethernet.hardwareStatus() == EthernetW5200) {
        Serial.println("W5200 Ethernet controller detected.");
      }
      else if (Ethernet.hardwareStatus() == EthernetW5500) {
        Serial.println("W5500 Ethernet controller detected.");
      }

      //Tells you whether the link is active.
      // LinkOFF could indicate the Ethernet cable is unplugged or defective.
      if (Ethernet.linkStatus() == Unknown) {
        Serial.println("Link status unknown. Link status detection is only available with W5200 and W5500.");
      }
      else if (Ethernet.linkStatus() == LinkON) {
        Serial.println("Link status: On");
      }
      else if (Ethernet.linkStatus() == LinkOFF) {
        Serial.println("Link status: Off");
      }

      while( Ethernet.linkStatus() == LinkOFF ) {
        Serial.println("\tplease connect the Ethernet cable");
        delay( DELAY );
      }
    }

    // LOOP ///////////////////////////////////////////////////////////////////
    void loop()
    {

      int LINK_STATUS = Ethernet.linkStatus();

      if ( LINK_STATUS == LinkOFF) {
        Serial.print("Ethernet link broken!\t");
        Serial.println("please connect the Ethernet cable");
        delay( DELAY );
        return;
      } else if( LINK_STATUS == Unknown ) {
        Serial.println("LINK_STATUS: Unknown");
        delay( DELAY );
        return;
      } else if( LINK_STATUS == LinkON ) {
        Serial.println("LOOP working as expected! (LINK_STATUS: ON)");
      }

      delay( DELAY );
    }
```

After a while, it gave me this output on the serial monitor (at the same time ping said "Destination Host Unreachable"):

    [...]
    10:57:21.207 -> LOOP working as expected! (LINK_STATUS: ON)
    10:57:22.203 -> LOOP working as expected! (LINK_STATUS: ON)
    10:57:23.200 -> LOOP working as expected! (LINK_STATUS: ON)
    10:57:24.197 -> LOOP working as expected! (LINK_STATUS: ON)
    10:57:25.195 -> Ethernet link broken! please connect the Ethernet cable
    10:57:26.192 -> LOOP working as expected! (LINK_STATUS: ON)
    10:57:27.188 -> LOOP working as expected! (LINK_STATUS: ON)
    10:57:28.186 -> LOOP working as expected! (LINK_STATUS: ON)
    10:57:29.216 -> Ethernet link broken! please connect the Ethernet cable
    10:57:30.213 -> Ethernet link broken! please connect the Ethernet cable
    10:57:31.210 -> Ethernet link broken! please connect the Ethernet cable
    10:57:32.207 -> Ethernet link broken! please connect the Ethernet cable
    10:57:33.204 -> LOOP working as expected! (LINK_STATUS: ON)
    10:57:34.202 -> Ethernet link broken! please connect the Ethernet cable
    10:57:35.198 -> Ethernet link broken! please connect the Ethernet cable
    10:57:36.194 -> Ethernet link broken! please connect the Ethernet cable
    10:57:37.224 -> Ethernet link broken! please connect the Ethernet cable
    10:57:38.221 -> Ethernet link broken! please connect the Ethernet cable
    10:57:39.219 -> LOOP working as expected! (LINK_STATUS: ON)
    10:57:40.216 -> LOOP working as expected! (LINK_STATUS: ON)
    10:57:41.213 -> LOOP working as expected! (LINK_STATUS: ON)
    10:57:42.210 -> LOOP working as expected! (LINK_STATUS: ON)
    10:57:43.207 -> LOOP working as expected! (LINK_STATUS: ON)
    10:57:44.236 -> LOOP working as expected! (LINK_STATUS: ON)
    10:57:45.232 -> Ethernet link broken! please connect the Ethernet cable
    10:57:46.228 -> LOOP working as expected! (LINK_STATUS: ON)
    10:57:47.225 -> LOOP working as expected! (LINK_STATUS: ON)
    10:57:48.222 -> LOOP working as expected! (LINK_STATUS: ON)
    10:57:49.218 -> Ethernet link broken! please connect the Ethernet cable
    10:57:50.216 -> Ethernet link broken! please connect the Ethernet cable
    10:57:51.212 -> Ethernet link broken! please connect the Ethernet cable
    10:57:52.242 -> Ethernet link broken! please connect the Ethernet cable
    10:57:53.239 -> Ethernet link broken! please connect the Ethernet cable
    10:57:54.235 -> Ethernet link broken! please connect the Ethernet cable
    10:57:55.231 -> Ethernet link broken! please connect the Ethernet cable
    10:57:56.227 -> Ethernet link broken! please connect the Ethernet cable
    [...]

Adding some new elements here.
I've also noticed that, sometimes, even if the LINK status is ON, the ping is not working. It is almost clear to me that the two things are completely uncorrelated.

I've made some experiments in changing also the MAC address (setting a MAC address which is different from the one I see on the label on the shield). The "*wrong*" MAC address seems not to be cause of problems.
Can it be that a MAC address misconfiguration on the Arduino firmware can make the things work the wrong way?

I've also made many attempts in disconnetting and re-connecting the ethernet cable to the shield without powering the Arduino off and I've experinced a series of different behaviours.

**1A)** disconnecting the ethernet cable:
* Serial monitor prints: "Ethernet link broken! please connect the Ethernet cable"
* ping stops;

**1B)** re-connecting the ethernet cable:
* on the Serial monitor LinkOn and LinkOff alternate between themselves, then, "LOOP working as expected! (LINK_STATUS: ON)" becomes stable;
* ping still prints "Destination Host Unreachable";

**2)** reset of the Arduino Board (not the reset on the shield)
* Serial monitor: "LOOP working as expected! (LINK_STATUS: ON)"
* ping works again;

**3A)** Trying to repeat the same procedure as before (1A). Disconnecting the Ethernet cable:
* Serial monitor prints "Ethernet link broken! please connect the Ethernet cable";
* ping stops;

**3B)** re-connecting the ethernet cable:
* on the Serial monitor LinkOn and LinkOff alternate between themselves, then, "LOOP working as expected! (LINK_STATUS: ON)" becomes stable;
* ping works again (which is a different behaviour from before!!!);

This problem is really difficult for me to debug. It seems we have a lot of variables to take into consideration here, which are not under my control: if I repeat the same procedure again and again, behaviour changes.

I'm not sure if it depends on the board, on the *W5500* chip, maybe on other things happening on the net. Is it possible?

I don't know how to write a code to be capable of detecting these malfunctions.

Thank you so much for your help.
na

title: Ethernet shield issues (defective shield?!)

Answers: 1

body:
I've had similar issues with the Ethernet V2 shield, which were probably caused by the (unused) SD Card interface on the Ethernet V2 shield interfering with Ethernet functionality (both use the SPI bus).

From what I could see in the [Ethernet Shield2 schematics](https://www.arduino.cc/en/uploads/Main/arduino-Ethernet-Shield2-V2-sch.pdf), there is no pull-up on the signal controlling the SD card Chip Select (D4/SD_CS), which means an unitialized I/O pin on the Arduino side could potentially cause random noise on the SD CS input.

My solution was to explicitly disable the SD Card interface CS, by setting pin 4 to high at the start of my `setup()` code.

I used the following code:

    #define SDSelect  4

    ... Other initialization code

    setup() {
        pinMode (SDSelect, OUTPUT);
        digitalWrite (SDSelect, HIGH);

        ... Code continues ...

This solved my issues with random crashing. I realize that I can't remember if there was an SD card present in the slot at the time.