# Question
Title: Pulse Sensor Working Bottom-Side-Up Better?
i recently bought me an pulse-heartbeat sensor. Connected him to my brand new M1 mini as well.

I wrote a piece of Code which just outputs the Raw ADC Value from A0 (where the pulse sensor is connected).

Now I'm confused.. When i open Serial Plotter, i get this:

Which is confusing because i don't get useable Values when putting the sensor up side down, which is the promoted way to do this (i guess!!)

When i press the other side against my wrist, i get this:  Which i can work with..

But it still doesnt look like some of those perfect diagrams on the internet.

Any can help me understand why i get this type of behaviour?

thanks, nice friday , luca

# Answer
From what I see, this is a pulse sensor that work with light. It emits a bright light beam, that is reflected by the pulsing blood. To work, it must send the light directed to your veins. It should work well on your finger, because the probability to target a vein directly is much greater with a small finger then e.g. a wide wrist. Also the veins in your finger are closer to your skin and the oxygen situation is more different while pulsing, so the blood has more impact on the reflection.

The second curve might be a light source in your room, or an electrical wave. (?) I doubt it is your heart, because, if the numbers below the graph are milliseconds, then your heartbeat would be between 10-15 beats / second, i.e. 600 - 900 per minute. That would be too much even for a hummingbird ;-).
> 1 votes

---
Tags: esp8266
---


# Question
Title: Trouble with PID code, variable error_x acting strange
I'm trying to get error\_x and error\_y to display the difference between the target and the position. For some reason I cannot get error\_x to function correctly. error\_y has the same code, but works correctly. Can anyone help?

Here is the code on my Arduino:

```
void setup() {
  Serial.begin(9600);
  Serial.print("Starting...\n");
}

int previousTime = 0;
float lastError_x = 0;
float lastError_y = 0;

void loop() {
  //pid variables
  float Kp = 1;
  float Ki = 0;
  float Kd = 0;
  float pos_x;
  float pos_y;
  float target_x;
  float target_y;
  float error_x;
  float error_y;
  int currentTime;
  int elapsedTime;
  float cumError_x;
  float cumError_y;
  float rateError_x;
  float rateError_y;
  float output_x;
  float output_y;

  //invkinematic variables
  float inVec[4] = {1, -1.5, 3};
  float height = 3.5;
  float B = 4;
  float L = 3;
  float U = 3.5;
  float plateRadius = 5.5;
  float alpha[4] = {0, 0, 0};
  float normVec[4];
  float p1[4] = {0,0,0};
  float p2[4] = {0,0,0};
  float p3[4] = {0,0,0};
  float crosskv[4] = {0,0,0};
  float normSave;
  float dotSave;
  float radius;
  float gamma;
  float beta;

  //serial variables
  char buf[32];
  char str_temp1[6];
  char str_temp2[6];
  char str_temp3[6];

  //PIXY CAMERA CODE (outputs x and y)

  pos_x = 1;
  pos_y = 1;

  //DETERMINE TARGET LOCATION
  //default:(0,0)
  target_x = 0;
  target_y = 0;

  //PID CODE (inputs x and y and outputs normal vector and height)

  error_x = target_x - pos_x;
  error_y = target_y - pos_y;

  dtostrf(error_x, 5, 3, str_temp1);
  dtostrf(error_y, 5, 3, str_temp2);
  sprintf(buf, "error1:%s error2:%s\n", str_temp1, str_temp2);
  Serial.print(buf);

  currentTime = millis();
  elapsedTime = currentTime - previousTime;
  if(elapsedTime==0){elapsedTime = 1;}

  cumError_x += error_x * elapsedTime / 1000;
  cumError_y += error_y * elapsedTime / 1000;
  rateError_x = (error_x - lastError_x)/(elapsedTime/1000);
  rateError_y = (error_y - lastError_y)/(elapsedTime/1000);

  output_x = Kp*error_x + Ki*cumError_x + Kd * rateError_x;
  output_y = Kp*error_y + Ki*cumError_y + Kd * rateError_y;

  inVec[0] = output_x/plateRadius;
  inVec[1] = output_y/plateRadius;
  inVec[2] = plateRadius;

  lastError_x = error_x;
  lastError_y = error_y;
  previousTime = currentTime;

  //INVKINEMATIC (inputs normal vector and height and outputs alpha values)

  normVec[0] = inVec[0]/(sqrt(inVec[0]*inVec[0]+inVec[1]*inVec[1]+inVec[2]*inVec[2]));
  normVec[1] = inVec[1]/(sqrt(inVec[0]*inVec[0]+inVec[1]*inVec[1]+inVec[2]*inVec[2]));
  normVec[2] = inVec[2]/(sqrt(inVec[0]*inVec[0]+inVec[1]*inVec[1]+inVec[2]*inVec[2]));

  p1[0] = normVec[2];
  p1[2] = -1*normVec[0];
  normSave = sqrt(p1[0]*p1[0]+p1[1]*p1[1]+p1[2]*p1[2]);
  p1[0] = plateRadius*p1[0]/normSave;
  p1[1] = plateRadius*p1[1]/normSave;
  p1[2] = plateRadius*p1[2]/normSave;

  crosskv[0] = normVec[1]*p1[2] - normVec[2]*p1[1];
  crosskv[1] = normVec[2]*p1[0] - normVec[0]*p1[2];
  crosskv[2] = normVec[0]*p1[1] - normVec[1]*p1[0];
  dotSave = normVec[0]*p1[0] + normVec[1]*p1[1] + normVec[2]*p1[2];
  p2[0] = -0.5*p1[0] + crosskv[0]*0.866 + normVec[0]*dotSave*1.5;
  p2[1] = -0.5*p1[1] + crosskv[1]*0.866 + normVec[1]*dotSave*1.5;
  p2[2] = -0.5*p1[2] + crosskv[2]*0.866 + normVec[2]*dotSave*1.5;
  normSave = sqrt(p2[0]*p2[0]+p2[1]*p2[1]+p2[2]*p2[2]);
  p2[0] = plateRadius*p2[0]/normSave;
  p2[1] = plateRadius*p2[1]/normSave;
  p2[2] = plateRadius*p2[2]/normSave;

  p3[0] = -0.5*p1[0] + crosskv[0]*-0.866 + normVec[0]*dotSave*1.5;
  p3[1] = -0.5*p1[1] + crosskv[1]*-0.866 + normVec[1]*dotSave*1.5;
  p3[2] = -0.5*p1[2] + crosskv[2]*-0.866 + normVec[2]*dotSave*1.5;
  normSave = sqrt(p3[0]*p3[0]+p3[1]*p3[1]+p3[2]*p3[2]);
  p3[0] = plateRadius*p3[0]/normSave;
  p3[1] = plateRadius*p3[1]/normSave;
  p3[2] = plateRadius*p3[2]/normSave;

  p1[2] = height+p1[2];
  p2[2] = height+p2[2];
  p3[2] = height+p3[2];

  radius = sqrt((p1[0]-B)*(p1[0]-B)+p1[1]*p1[1]+p1[2]*p1[2]);
  gamma = atan2(p1[2],sqrt((p1[0]-B)*(p1[0]-B)+(p1[1])*(p1[1])));
  beta = acos((L*L+radius*radius-U*U)/(2*L*radius));
  alpha[0] = 3.1416 - (gamma + beta);

  radius = sqrt((p2[0]+0.5*B)*(p2[0]+0.5*B)+(p2[1]-0.866*B)*(p2[1]-0.866*B)+(p2[2])*(p2[2]));
  gamma = atan2(p2[2],sqrt((p2[0]+0.5*B)*(p2[0]+0.5*B)+(p2[1]-0.866*B)*(p2[1]-0.866*B)));
  beta = acos((L*L+radius*radius-U*U)/(2*L*radius));
  alpha[1] = 3.1416 - (gamma + beta);

  radius = sqrt((p3[0]+0.5*B)*(p3[0]+0.5*B)+(p3[1]+0.866*B)*(p3[1]+0.866*B)+(p3[2])*(p3[2]));
  gamma = atan2(p3[2],sqrt((p3[0]+0.5*B)*(p3[0]+0.5*B)+(p3[1]+0.866*B)*(p3[1]+0.866*B)));
  beta = acos((L*L+radius*radius-U*U)/(2*L*radius));
  alpha[2] = 3.1416 - (gamma + beta);

  dtostrf(normVec[0], 5, 3, str_temp1);
  dtostrf(normVec[1], 5, 3, str_temp2);
  dtostrf(normVec[2], 5, 3, str_temp3);
  sprintf(buf, "a1:%s a2:%s a3:%s\n", str_temp1, str_temp2, str_temp3);
  Serial.print(buf);

  //OUTPUT alpha to servos

  delay(1000);
}

```

Here is the output with the error:

```
Starting...
error1: error2:-1.000
a1:  NAN a2:  NAN a3:

error1: error2:-1.000
a1: a2:-0.033 a3:

error1: error2:-1.000
a1: a2:-0.033 a3:

error1: error2:-1.000
a1: a2:-0.033 a3:

error1: error2:-1.000
a1: a2:-0.033 a3:

```

# Answer
> 0 votes
Consider enlarging your character arrays. When creating strings an extra character is likely necessary to indicate the end of a string. This is usually the null character or zero. If missing, many string related features will not see an end of a string and likely cause unexpected results.

---
Tags: arduino-uno
---


# Question
Title: Arduino Mega timeout communication with programmer error
I have an Arduino Mega 2560 and it was working fine until about lunch time when I started getting this error:

```
avrdude: stk500v2_ReceiveMessage(): timeout
avrdude: stk500v2_getsync(): timeout communicating with programmer

```

I know it isn't the code I'm running as I tried to load it onto an Uno and it seemed to load without issue. I need to use the Mega as it has more ports, though.

From what I have read this is potentially an issue with the bootloader and is possibly related to the current version of Arduino. I know virtually nothing about the bootloader; all I know is that it is used to upload code to the Arduino (I think...), therefore I have a fear of just messing around with related files unknowingly.

These pages are the ones I've been looking at, but like I said, I don't really know enough to feel comfortable with just messing around with the files.

I tried uninstalling my Mega totally, then reinstalling it. I also downloaded an older version of Arduino (0022) and neither option seemed to work.

I don't know what to do, or how to change the 'AVR' files if necessary.

# Answer
> 3 votes
The bootloader on an arduino is just a piece of software written to enable you to update your sketches using the usb connection. Without the bootloader you can't upload sketches using just the arduino ide.

More information about the bootloader can be found here: http://arduino.cc/en/Guide/Environment?from=Tutorial.Bootloader Look under the heading entitled uploading which explains the part the bootloader plays in uploading sketches.

When you use the "Burn Bootloader" button in the arduino ide it will attempt to write a new copy of the bootloader onto the attached Arduino board. To do this the board must be attached in a specific manner - that is - using the icsp/isp header rather than the usb cable.

Now to program the avr chip directly you have to use an external (hardware) programmer. Fortunately you don't have to buy one if you have a second arduino because the second arduino can be used as a programmer. Instructions for doing so can be found here: http://arduino.cc/en/Tutorial/ArduinoISP

Even more info about the bootloader: http://arduino.cc/en/Hacking/Bootloader?from=Main.Bootloader

# Answer
> 1 votes
Unfortunately this error refers to many different issues and there are so many posts here and on other platforms none with a definite answer. Maybe Arduino team should try to give better errors to differentiate. But I have tried to answer the same question here in this SO post.

what solved my issue was to go to Tools\>Boards\>Board Manager... select "updatable" for "Type" on top left and then select the updatable packages below and click on update.

# Answer
> 1 votes
I got this same error when my Arduino COM port was busy with other apps. I closed that app and upload Arduino sketch and error disappeared.

---
Tags: bootloader, arduino-mega, avrdude
---


title: How to read input pin on MCP23017?

text:
# Question
Title: How to read input pin on MCP23017?
I'm working to develop a simple code for MCP23017 that I want to use to run LCD128x64.

I was succeeded to set `IODIRB` as output and blink LED as a test.

Now I want to read the pin state, but I couldn't. Here's my code. I'm using the nice twi library that comes with Wire library.

```
uint8_t mcp23017_read(uint8_t add_reg){
    uint8_t data;
    twi_writeTo(MCP23017_ADD,add_reg,2,1,0);
    twi_readFrom(MCP23017_ADD,data,1,1);

    return data;
}

```

I've tried this version too:

```
uint8_t *mcp23017_read(uint8_t add_reg){
    uint8_t data[1];
    twi_writeTo(MCP23017_ADD,add_reg,2,1,0);
    twi_readFrom(MCP23017_ADD,data,1,1);

    return *data;
}

```

==================================================

Here's Arduino call function:

```
void loop() {
  // put your main code here, to run repeatedly:
  data = mcp23017_read(GPIOB);
  Serial.println(data);
  delay(100);
}

```

# Answer
I don't know how this lib works. But I'm pretty sure that you have to pass a pointer onto the `data` variable into the `twi_readFrom` method.

```
uint8_t mcp23017_read( uint8_t add_reg )
{
    uint8_t data;
    twi_writeTo( MCP23017_ADD, add_reg, 2, 1, 0 );
    // I inserted an & below
    twi_readFrom( MCP23017_ADD, &data, 1, 1 );

    return data;
}

```

Or in case of the second function:

```
// I removed the star operator
uint8_t mcp23017_read(uint8_t add_reg)
{
    uint8_t data[1];

    twi_writeTo( MCP23017_ADD, add_reg, 2, 1, 0 );
    // you pass the pointer to the array element 0
    twi_readFrom( MCP23017_ADD, data, 1, 1 );

    // I returned the element 0
    return data[0];
}

```

**Update:**

Just for completeness: The OP found also a failure on the write function. He had posted a separate answer, I voted up to mark it. Because this is the accepted answer, I also copied his post to here for completeness and the readers convenience.

Original post by R1S8K:

> OK, I found a the answer and it was a good lesson in dealing with functions that receives pointers.
>
> I forgot that the writeTo function also receives a pointer and I have to pass an array for both read/write functions.
>
> ```
> void mcp23017_read(uint8_t *add_reg, uint8_t *buffer){
>     twi_writeTo(MCP23017_ADD, add_reg, 1, 1, 1);
>     twi_readFrom(MCP23017_ADD, buffer, 1, 1);
> }
>
> ```
> 2 votes

# Answer
OK, I found one little mistake in my coding.

I forgot that the `writeTo` function also receives a pointer and I have to pass an array for both read/write functions.

```
void mcp23017_read(uint8_t *add_reg, uint8_t *buffer){
    twi_writeTo(MCP23017_ADD, add_reg, 1, 1, 1);
    twi_readFrom(MCP23017_ADD, buffer, 1, 1);
}

```
> 1 votes

---
Tags: arduino-uno, input, io-expander
---


# Question
Title: How to wait a certain time before doing something while running other code?
I have a project where I'm using the HX711 library with a loadcell to weigh in a fruit that is on a conveyor belt. Each fruit has a weight which needs to be classed. The bigger fruits (200g) are class A so they have to "fall down" the conveyor belt at a later stage. The smaller fruits fall down earlier. This has to be done on a timed basis.

What I want to do is get the fruit size , calculate the class (using weight) and then send an interrupt to the dropping mechanism after x time. But while it must wait to drop the next fruit will be have come in and might be smaller than the first.

I can already weigh in and calculate the class of fruits. I've also done this in C using multithreading but adruino uno doesn't support that.

I also have to mention that there is about 50-200 fruits on a single conveyor belt at any given time.

# Answer
You can use timestamp to avoid the blocking code. See BlinkWithoutDelay example
> 0 votes

---
Tags: arduino-uno
---


# Question
Title: Two adruino are connected to the raspberry via usb, but one is reconnected during processing code is running
I try to solve this a month..but still problem...

I want to make below led-matrix spectrum.

Thumbnail image

https://youtu.be/X35HbE7k3DA

**※Environment**

Device UML

One Raspberry pi 3 : 2019-09-26-raspbian-buster-full

Two arduino uno with each matrix shield and 16x32 matrix

One usb Microphone

If i attached two arduino Uno to raspberry pi and try to run Processing code(.pde) , one of them is reattached to raspberry pi.

The other one is still working well..

If i connect these arduinos to windows and running pde file...It works well. (two matrix are showing spectrum well)

What should I do??? Is this code problem? or raspberry problem?

I really need to solve this...

**I already tried....**

1. Reloaded ino code to both arduino Uno. (both arduino has same code)
2. Changed boardrate number 115200 -\> other number (but it must be 115200 to running well)
3. Add arduino to udev rules like below link. https://www.intorobotics.com/how-to-setup-raspberry-pi-to-identify-two-arduino-devices/
4. Cross exchange each matrix and arduino.
5. Try to use arduino mega with same code.

**Here is the arduino code(.ino) and Processing Code(.pde)** https://github.com/snskreationz/Real-Time-RGB-Matrix-Spectrum-Analyzer

**arduino Uno Matrix Pin number**

```
#define CLK 8
#define LAT 10
#define OE  9
#define A   A0
#define B   A1
#define C   A2

```

**Main processing code**

```
import ddf.minim.analysis.*;
import ddf.minim.*;
import processing.serial.*;

Serial port1;
Serial port2;

Minim minim;
AudioInput in;
FFT fft;

int buffer_size = 4096;
float sample_rate = 200000;

int freq_width = 250; // <-O-> set the frequency range for each band over 400hz. larger bands will have less intensity per band. smaller bands would result in the overall range being limited

//arrays to hold the 64 bands' data
int[] freq_array = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
float[] freq_height = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};

void setup()
{
  size(200, 200);

  minim = new Minim(this);
  port1 = new Serial(this, "COM8" , 115200); // <-O-> set baud rate and port for first RGB matrix
// Here can be changed to "/dev/ttyACM0" via Raspberry pi
  //port2 = new Serial(this, "COM5" , 115200); // <-O-> set baud rate and port for second RGB matrix
// Here can be changed to "/dev/ttyACM1" via Raspberry pi

  in = minim.getLineIn(Minim.MONO,buffer_size,sample_rate);

  // create an FFT object that has a time-domain buffer
  // the same size as line-in's sample buffer
  fft = new FFT(in.bufferSize(), in.sampleRate());
  // Tapered window important for log-domain display
  fft.window(FFT.HAMMING);
}

```

**Here are the kernel logs for Raspebrry pi**

```
Nov 11 00:17:27 raspberrypi kernel: [ 5974.165722] Under-voltage detected! (0x00050005)
Nov 11 00:17:27 raspberrypi kernel: [ 5974.665649] usb 1-1.3: new full-speed USB device number 9 using dwc_otg
Nov 11 00:17:27 raspberrypi kernel: [ 5974.809539] usb 1-1.3: New USB device found, idVendor=2341, idProduct=0043, bcdDevice= 0.01
Nov 11 00:17:27 raspberrypi kernel: [ 5974.809556] usb 1-1.3: New USB device strings: Mfr=1, Product=2, SerialNumber=220
Nov 11 00:17:27 raspberrypi kernel: [ 5974.809566] usb 1-1.3: Manufacturer: Arduino (www.arduino.cc)
Nov 11 00:17:27 raspberrypi kernel: [ 5974.809576] usb 1-1.3: SerialNumber: 55639313932351518040
Nov 11 00:17:27 raspberrypi kernel: [ 5974.810729] cdc_acm 1-1.3:1.0: ttyACM0: USB ACM device ---------------------> connected first arduino
Nov 11 00:17:28 raspberrypi kernel: [ 5975.685661] usb 1-1.2: new full-speed USB device number 10 using dwc_otg
Nov 11 00:17:28 raspberrypi kernel: [ 5975.829541] usb 1-1.2: New USB device found, idVendor=2341, idProduct=0043, bcdDevice= 0.01
Nov 11 00:17:28 raspberrypi kernel: [ 5975.829558] usb 1-1.2: New USB device strings: Mfr=1, Product=2, SerialNumber=220
Nov 11 00:17:28 raspberrypi kernel: [ 5975.829569] usb 1-1.2: Manufacturer: Arduino (www.arduino.cc)
Nov 11 00:17:28 raspberrypi kernel: [ 5975.829578] usb 1-1.2: SerialNumber: 8563431373935121D0B2
Nov 11 00:17:28 raspberrypi kernel: [ 5975.830752] cdc_acm 1-1.2:1.0: ttyACM1: USB ACM device --------------------->  connected second arduino
Nov 11 00:17:33 raspberrypi kernel: [ 5980.405877] Voltage normalised (0x00000000) --------------------->  almost at this time starting processing code
Nov 11 00:17:37 raspberrypi kernel: [ 5985.121964] usb 1-1.2: USB disconnect, device number 10
Nov 11 00:17:37 raspberrypi kernel: [ 5985.122315] cdc_acm 1-1.2:1.0: failed to set dtr/rts
Nov 11 00:17:38 raspberrypi kernel: [ 5985.425669] usb 1-1.2: new full-speed USB device number 11 using dwc_otg
Nov 11 00:17:38 raspberrypi kernel: [ 5985.569812] usb 1-1.2: New USB device found, idVendor=2341, idProduct=0043, bcdDevice= 0.01
Nov 11 00:17:38 raspberrypi kernel: [ 5985.569831] usb 1-1.2: New USB device strings: Mfr=1, Product=2, SerialNumber=220
Nov 11 00:17:38 raspberrypi kernel: [ 5985.569843] usb 1-1.2: Manufacturer: Arduino (www.arduino.cc)
Nov 11 00:17:38 raspberrypi kernel: [ 5985.569853] usb 1-1.2: SerialNumber: 8563431373935121D0B2
Nov 11 00:17:38 raspberrypi kernel: [ 5985.571468] cdc_acm 1-1.2:1.0: ttyACM2: USB ACM device --------------------->  reattached second arduino automatically
Nov 11 00:17:39 raspberrypi kernel: [ 5986.645829] Under-voltage detected! (0x00050005)
Nov 11 00:17:43 raspberrypi kernel: [ 5990.805775] Voltage normalised (0x00000000)

```

I really want to run both arduino spectrum via raspberry pi.

# Answer
> 0 votes
`Under-voltage detected!` I think it says it all. Rapsberry have many times problem to feed itself from "common power source", not mentioning attached devices. Especially, if you power your LEDs from it too.

You need better power source for Rapsberry (and maybe even power it from pins, but then you need read much more to not damage it) and other powersource for those LEDs.

On normal PC the Power Source is way more powerfull and can feed a LOT of power to each USB.

---
Tags: arduino-uno, serial, usb, raspberrypi, processing-lang
---


# Question
Title: Use ATtiny85 to perform initial config on a Cisco router using its USB console port
We have 200+ brand new Cisco routers that have USB console ports (but not the old RJ45 serial console ports). This is quite frustrating because the routers didn't ship with console cables and Cisco wants to charge $60 for their proprietary USB-\>RJ45 serial adapters.

When I plug the router in to a computer using a standard USB cable (mini USBb on one end and USB on the other end), it shows up as a virtual com port and allows me to configure the router if I have a VCP driver installed. More specifically it shows up as a "CP2105 Dual USB to UART Bridge Controller". Here's the full `lsusb -v` output for the router:

```
Bus 001 Device 005: ID 10c4:ea70 Cygnal Integrated Products, Inc. CP210x UART Bridge
Device Descriptor:
  bLength                18
  bDescriptorType         1
  bcdUSB               2.00
  bDeviceClass            0 (Defined at Interface level)
  bDeviceSubClass         0
  bDeviceProtocol         0
  bMaxPacketSize0        64
  idVendor           0x10c4 Cygnal Integrated Products, Inc.
  idProduct          0xea70 CP210x UART Bridge
  bcdDevice            1.01
  iManufacturer           1 Silicon Labs
  iProduct                2 CP2105 Dual USB to UART Bridge Controller
  iSerial                 5 12345678
  bNumConfigurations      1
  Configuration Descriptor:
    bLength                 9
    bDescriptorType         2
    wTotalLength           55
    bNumInterfaces          2
    bConfigurationValue     1
    iConfiguration          0
    bmAttributes         0x80
      (Bus Powered)
    MaxPower              100mA
    Interface Descriptor:
      bLength                 9
      bDescriptorType         4
      bInterfaceNumber        0
      bAlternateSetting       0
      bNumEndpoints           2
      bInterfaceClass       255 Vendor Specific Class
      bInterfaceSubClass      0
      bInterfaceProtocol      0
      iInterface              3 Enhanced Com Port
      Endpoint Descriptor:
        bLength                 7
        bDescriptorType         5
        bEndpointAddress     0x81  EP 1 IN
        bmAttributes            2
          Transfer Type            Bulk
          Synch Type               None
          Usage Type               Data
        wMaxPacketSize     0x0040  1x 64 bytes
        bInterval               0
      Endpoint Descriptor:
        bLength                 7
        bDescriptorType         5
        bEndpointAddress     0x01  EP 1 OUT
        bmAttributes            2
          Transfer Type            Bulk
          Synch Type               None
          Usage Type               Data
        wMaxPacketSize     0x0040  1x 64 bytes
        bInterval               0
    Interface Descriptor:
      bLength                 9
      bDescriptorType         4
      bInterfaceNumber        1
      bAlternateSetting       0
      bNumEndpoints           2
      bInterfaceClass       255 Vendor Specific Class
      bInterfaceSubClass      0
      bInterfaceProtocol      0
      iInterface              4 Standard Com Port
      Endpoint Descriptor:
        bLength                 7
        bDescriptorType         5
        bEndpointAddress     0x82  EP 2 IN
        bmAttributes            2
          Transfer Type            Bulk
          Synch Type               None
          Usage Type               Data
        wMaxPacketSize     0x0020  1x 32 bytes
        bInterval               0
      Endpoint Descriptor:
        bLength                 7
        bDescriptorType         5
        bEndpointAddress     0x02  EP 2 OUT
        bmAttributes            2
          Transfer Type            Bulk
          Synch Type               None
          Usage Type               Data
        wMaxPacketSize     0x0020  1x 32 bytes
        bInterval               0
Device Status:     0x0000
  (Bus Powered)

```

Is it possible to have an ATtiny85 board (eg Digispark) interface with the router via its USB console port to send several commands over the link to perform a perform basic initial config?

# Answer
> 2 votes
It's been a couple of decades since I was programming Cisco routers, firewalls and switches but I appreciate you pain. Like @Gerben says, you need a bigger processor, an ATtiny85 isn't going to be able to hold a lot of config and even the basic configs I used were about 4 to 6KB.

If there is anything in the configs that is different, you idea is going to hit problems. Are the device names and passwords all the same? In which case you probably want the engineer to be able to set some configuration data in you "programmer", could they set this specialisation data using their mobile phone?

I doubt you will have any problem connecting an "Arduino" via serial (RS232) to a Cisco router. However you now have to encapsulate the serial in "USB", which I don't think will be straight forward for an "Arduino".

I can't think of an option that doesn't require power, but as an alternative to your idea what about using a Raspberry Pi to connect to the router via USB. Stick a touch screen on it and a battery pack to power it.

# Answer
> 1 votes
Can I use a ATtiny85 board (eg Digispark) as a USB CDC device?

**Yes!**

If I have got this right, to be able to communicate with a USB serial device you need to have USB CDC support and if you want it to fake a keyboard/mouse you need HID.

The Digispark have a CDC library https://digistump.com/wiki/digispark/tutorials/digicdc

But it has its **limitations**, take a lot of RAM ( ~2K) so to use a Arduino Leonard/Arduino Micro make more sens and then you could add a SD card as well so you can have your commands easily modified on a SD card.

I have the same idea, but I fetch the config from a TFTP source so my commands needed on the Digispark/Leonardo/Micro is minimal.

---
Tags: serial, usb, communication, softwareserial, attiny
---


# Question
Title: I am trying to combine a button's coding and servo's coding. But it is still cannot be verified. What have I done wrong?
# include

Servo myservo;

void setup(){ myservo.attach(8); pinMode(buttonPin, INPUT); }

void loop() { myservo.write(0); delay(3); myservo.write(90); delay(3); } const int inPin=8; const int outPin = 9; int currentState = LOW; currentState = digitalRead (inPin); if (currentState== HIGH) digitalWrite (outPin,HIGH); else digitalWrite (outPin,HIGH); delay(10); }

# Answer
> 0 votes
Do NOT use two loop() and setup() function.

You can refer to a similar combination between Servo Motor code and Potentiometer code here.

---
Tags: servo, button
---


# Question
Title: Compute the size of an array that was passed as a parameter to a function
When passing an array to a function, you usually pass the length of the array along with it. You can compute the size of the array with `sizeof(myArray)/sizeof(myArray[0])`, which works just fine.

However, if you try to do this within the function that you pass the array to, this doesn't return the length of the array - eg. if it is an `int` array, it returns 1, if it is a `double` array, it returns 0.

Why is that so and is there any way to compute the size of an array that was passed as a parameter?

# Answer
> 2 votes
You can't. You are passing a *pointer* to the array, and `sizeof` will give you the size of that pointer (2 on an 8-bit Arduino).

Instead the normal way is to pass the size of the array as a parameter to your function.

```
myFunction(myArray, sizeof(myArray) / sizeof(myArray[0]));

```

---
Tags: array, functions
---


# Question
Title: Error: invalid application of 'sizeof' to incomplete type 'int []' when trying to compute the size of an array in a library
I have created a library that contains an array. This is the .h file:

```
class Lib {
  public:
    static int arr[];
};

```

And this is the .cpp file:

```
#include "Lib.h"

int Lib::arr[] = {0, 1, 2, 3};

```

When trying to compute the size of this array from within the library, it works just fine. When trying to do this from a sketch, I get the error mentioned in the title. This is the sketch I'm using:

```
#include <Lib.h>

void setup() {
  sizeof(Lib::arr);
}

void loop() {}

```

What is the problem here?

# Answer
The reason is that in your sketch you import only the header file (which is good). However, there it is an array (`int[]`), not the initialized array.

For that you would need to include the cpp but that is bad practice (if even possible).

So instead, create a new (constant) variable, and assign it.

(more or less pseudo code, due to lack of a compiler):

Lib.h:

```
class Lib {
  public:
    static int arr[];
    static int arr_length;
};

```

Lib.cpp:

```
#include "Lib.h"

int Lib::arr[] = {0, 1, 2, 3};
int Lib::arr_length = sizeof(Lib::arr);

```

Sketch:

```
#include <Lib.h>

void setup() {
  Lib::arr_length;
}

void loop() {}

```

See also the comment of LukasFun below. It is also possible to set the size of the array in the header file.

My advice though is keeping all assignments in the implementation (cpp) file. The header file is for defining items, the implementation file for initializing/assigning. But it works too, to initialize items in the header file.
> 1 votes

---
Tags: programming, library, array, compilation-errors
---


# Question
Title: wake from powerDown to check sensor then put back to sleep
I am using an Arduino Pro Mini with various sensors. I am powering it with 2 3.7v 3400mA batteries which I recharge with a solar panel. I take a reading from the batteries and if the reading is above a certain number I disconnect the solar panel from the batteries using a relay. Then when the battery reading gets below a certain number I switch back on the solar panel using the same relay. This all works fine. To conserve energy I want to delay the loop to the Arduino's activities for say two hours. Right now I call lowPower(); at the end of the loop{. void lowPower(){ is

```
LowPower.powerDown(SLEEP_8S,ADC_OFF,BOD_OFF);

```

Which I continually repeat for the two hours I want. The problem is during this two hours the high or low limit of the battery charge could be reached but I wouldn't know it.

What I would like to do is repeat

```
LowPower.powerDown(SLEEP_8S,ADC_OFF,BOD_OFF);

```

for 15 minutes and then check the batteries and turn on or off the solar charger as need. Then repeat the whole thing until two hrs is reached. At that point I would rerun the loop{ to check all sensors etc. I have tried the following

```
   void loop(){
    //code to run other sensors etc.
    if (Delay ==4) {
  delay(180000);
//check the battery to begin with
sensorBatValue = analogRead(batteryInPin);
  delay(500);
if(chargeSwitch ==1){
 if(sensorBatValue < batteryNoCharge) {
  }
 else if(sensorBatValue > batteryNoCharge) {
     digitalWrite(10,HIGH);
   delay(1000);
   digitalWrite(10,LOW);
   chargeSwitch = 2;
  }
   }
else if(chargeSwitch ==2){
    if(sensorBatValue > batteryCharge) {
    }
    else if(sensorBatValue < batteryCharge) {
      digitalWrite(13,HIGH);
    delay(1000);
   digitalWrite(13,LOW);
   chargeSwitch = 1;
    }
  }
//put to sleep
lowPower();
//check battery again
delay(180000);//real
sensorBatValue = analogRead(batteryInPin);
  delay(500);
if(chargeSwitch ==1){
 if(sensorBatValue < batteryNoCharge) {
  }
 else if(sensorBatValue > batteryNoCharge) {
     digitalWrite(10,HIGH);
   delay(1000);
   digitalWrite(10,LOW);
   chargeSwitch = 2;
  }
   }
else if(chargeSwitch ==2){
    if(sensorBatValue > batteryCharge) {
    }
    else if(sensorBatValue < batteryCharge) {
      digitalWrite(13,HIGH);
    delay(1000);
   digitalWrite(13,LOW);
   chargeSwitch = 1;
    }
  }
// put to sleep
lowPower();
//repeat for total of 2 hours.
}

 void lowPower(){
    LowPower.powerDown(SLEEP_8S,ADC_OFF,BOD_OFF);
    LowPower.powerDown(SLEEP_8S,ADC_OFF,BOD_OFF);
    LowPower.powerDown(SLEEP_8S,ADC_OFF,BOD_OFF);
    LowPower.powerDown(SLEEP_8S,ADC_OFF,BOD_OFF);
    //repeat until 15 minutes is reached
}

```

This doesn't seem to work. The Arduino waits the correct time but from what I can tell the battery is never checked.

Or should I try

```
    void loop(){
    everything
    if (Delay ==4) {
  delay(180000);//real
  sensorBatValue = analogRead(batteryInPin);
  delay(500);
if(chargeSwitch ==1){
 if(sensorBatValue < batteryNoCharge) {
  }
 else if(sensorBatValue > batteryNoCharge) {
     digitalWrite(10,HIGH);
   delay(1000);
   digitalWrite(10,LOW);
   chargeSwitch = 2;
  }
   }
else if(chargeSwitch ==2){
    if(sensorBatValue > batteryCharge) {
    }
    else if(sensorBatValue < batteryCharge) {
      digitalWrite(13,HIGH);
    delay(1000);
   digitalWrite(13,LOW);
   chargeSwitch = 1;
    }
  }
    //include the checking of the battery inside the lowPower
    void lowPower(){
    LowPower.powerDown(SLEEP_8S,ADC_OFF,BOD_OFF);
    LowPower.powerDown(SLEEP_8S,ADC_OFF,BOD_OFF);
    LowPower.powerDown(SLEEP_8S,ADC_OFF,BOD_OFF);
    LowPower.powerDown(SLEEP_8S,ADC_OFF,BOD_OFF);
    etc.
    LowPower.powerDown(SLEEP_8S,ADC_OFF,BOD_OFF);
    //check battery after 15 min.
    delay(500);
       sensorBatValue = analogRead(batteryInPin);
    delay(500);
    if(chargeSwitch ==1){
     if(sensorBatValue < batteryNoCharge) {
     }
     else if(sensorBatValue > batteryNoCharge) {
         digitalWrite(10,HIGH);
       delay(1000);
       digitalWrite(10,LOW);
       chargeSwitch = 2;
      }
       }
    else if(chargeSwitch ==2){
        if(sensorBatValue > batteryCharge) {
       }
        else if(sensorBatValue < batteryCharge) {
          digitalWrite(13,HIGH);
        delay(1000);
       digitalWrite(13,LOW);
       chargeSwitch = 1;
        }
      }
    //then repeat to two hours
    }

```

Do I need to do something to wake up the Arduino and Turn on the battery sensor pin and turn back on ADC?

Not sure how to do this Please HELP.

# Answer
> 1 votes
You have to note that if you go in "power down" mode, you will not be able to get the time as `millis()` will return the wrong time.

If you just want 15 minutes, you can just put it inside a for loop:

```
for(int j=0;j<112;j++) LowPower.powerDown(SLEEP_8S,ADC_OFF,BOD_OFF);

```

So the next instruction will be executed approximately after 15 minutes (15 * 60 / 8 = 112).

I made a similar project with a Teensy. With it you have more functions for the time. Just remember that with the power down, you will not be able to have any time function without an external time module on the Arduino.

Battery measurement schematics is also important. If you insert 2 resistors like 1M and 4M you will not be able to measure it since the measurement is done internally over multiple measurements and the current is not enough to measure it more than 1 time every 10-20ms. You have to add a capacitor to read a good value.

# Answer
> 0 votes
Try to use an external timer. I have the same problem approximatly.

# Answer
> 0 votes
In your function `lowPower()`, instead of repeating the LowPower.powerDown(), loop over that call enough time to make up the total sleep-time you need. That's the general case. For your specific case, where you need 15-minute intervals and 2-hour intervals, `lowPower()` should loop 113 times (15:04, since 15 \*60 doesn't divide evenly by 8). In your `loop()` function, loop over `lowPower()` 8 times (to make 2 hours), and each time it returns, check your battery. When the loop over `lowPower()` exits, it's time to do your "every 2 hours" jobs.

Because the 8s doesn't evenly divide 15 minutes, this timing isn't exact (but neither is the watchdog timer!), so you may want to tweak things a little, such as using a 4-second sleep, which does divide evenly.

Also, when I indented your code, I found `void lowPower()` nested inside the `loop()` function. C doesn't support that. If that was unintentional, check the pairing of your braces.

---
Tags: arduino-nano, power, sleep
---


# Question
Title: Creating an array with the length coming from a library
When creating an array like in the sketch

```
#include <Lib.h>

int myArray[Lib::len];

void setup() {}

void loop() {}

```

the variable len must be an integer constant that is known at compile time. Like shown in the sektch, I want to put the length of the array into a library and get it from there. The problem is that for this to work, you have to initialize the constant already in the .h file, which is against proper library standards. This is how you would do this (.h file of the library):

```
class Lib {
  public:
    static const int len = 4;
};

```

The .cpp file doesn't even have to contain anything in this case. The proper way to do things in a library would be like this though:

The .h file:

```
class Lib {
  public:
    static const int len;
};

```

The .cpp file:

```
#include "Lib.h"

const int Lib::num = 4;

```

But if done like this, `len` doen't have a value at compile time since the sketch only includes the .h file and not the .cpp file.

Is there any way to intitialize an array in a sketch with its length coming from a library while maintaining proper library design?

# Answer
> 0 votes
There is absolutely nothing wrong with putting it in the header.

> §9.4.2/4 If a static data member is of const integral or const enumeration type, its declaration in the class definition can specify a constant-initializer which shall be an integral constant expression (5.19). In that case, the member can appear in integral constant expressions. The member shall still be defined in a name- space scope if it is used in the program and the namespace scope definition shall not contain an initializer.

Since you're just using it as a simple constant "integral" value there is nothing wrong with putting it in the header.

---
Tags: programming, library, array, compilation-errors, constants
---


# Question
Title: command keeps echoing because web page tries refreshing
I want to execute a action only once when I press web page button but as the page tries refreshing the action gets executed in a loop. I am using the wifimanualwebserver example for esp8266. Please suggest what should I do?

# Answer
> 0 votes
Not sure if it possible in your case, but you might send and ID with it which you increase every time the button has been (really) clicked (thus not refreshed). On the receiver side, check if the ID is already received, if yes, do not execute it.

---
Tags: esp8266, wifi, nodemcu, ethernet, web-server
---


# Question
Title: Accelstepper.runToPosition() is working fine. Accelstepper.run() does nothing
I have a complex sketch with Arduino Uno, Bluetooth Serial Com using altSoftSerial, serial com using SoftwareSerial and Serial communication with PC.

I want to move one stepper motor and stop it when a signal is received. I use A4988 Pololu driver and NEMA 17 bipolar stepper motor.

This code is working fine. MyStepper.moveTo(position); MyStepper.runToPosition();

If I change the code to MyStepper.moveTo(position); MyStepper.run(); so that the running does not block my code the motor does nothing Absolutely no movement.

The ground of the motor power supply is connected with the ground of Arduino. The motor is working fine with blocking movements.

# Answer
You didn't include any code for us to see what the actual issue is, but I'm willing to guess that you didn't take into account that the run command requires repeated firing.

If your program comes to a point where there's an instance of runToPosition, the blocking function stops the program until the stepper reaches the position specified.

When your program comes to an instance of run(), it fires off a pulse and carries on reading. So you have to use a loop.

```
stepperMotor.moveTo(3000);
stepperMotor.runToPosition();
// reaches destination

stepperMotor.moveTo(3000);
stepperMotor.run();
// moves a single step

stepperMotor.moveTo(3000);
while (stepperMotor.distanceToGo > 0) {
stepperMotor.run();
}
// reaches destination

```

The reason you'd use run over runToPosition is to allow for continuous operations / parameters to be executed. For example, two stepper motors running simultaneously:

```
stepperMotor1.moveTo(5000);
stepperMotor2.moveTo(3000);
while ((stepperMotor1.distanceToGo > 0) && (stepperMotor2.distanceToGo > 0)) {
stepperMotor1.run();
stepperMotor2.run();
}
// Both motors will run, but will both stop when either of them reaches their destination.

```

Depending on the speed of your microprocessor, you can create some sophisticated instruction sets for your motor(s).
> 2 votes

# Answer
The problem is at blocking delays. The Run function is interrupted by any other action of program. So you have to call it all the time. A call to run is required in the loop and I wrote a simple mydelay function which solves the problem if you have to use delay for bluetooth communication or other purpose.

```
int mydelay(int j) {
  long endmillis;
  endmillis = millis() + j;
  while (millis() < endmillis) {
  MyStepper.run();
  }

```

I hope I help someone because it took me a while to figure this out as a newbie to Arduino.
> -1 votes

---
Tags: arduino-uno
---


# Question
Title: can I program a nano over SPI with another nano?
I'm fairly new to arduino, but I want to program a nano over SPI to skip the bootloader. I know I can program the nano with an uno as a programmer to do this, but I don't have an uno, but I do have a couple of nanos. Can I set up one as a programmer, connect it to another over SPI, and program the 2nd?

# Answer
Yes, you can. They use ATmega328 / Atmega328P microcontrollers, which are basically the same.

(The differencies of those microcontrollers are about Brown Out Detection - how they could be set to react on too low voltage. No problem in nearly any Arduino operation.)

The boards differ mainly in the board size and places for pins.
> -1 votes

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


# Question
Title: I have to make an LED with an ultrasonic distance sensor, where the LED blinks faster when getting closer than a specific distance
I already have this code, but I do not know how to make the LED blink.

CODE:

```
const int ledPin = 6; // The pin of your LED, D06
const int trigPin = 5; // The pin to which the TRIG is connected, D05
const int echoPin = 4; // The pin to which the ECHO is connected, D04
const int ledOnTime = 1000;
// The time that the LED stays on, after detecting the motion (in milliseconds, 1000ms = 1s)
const int trigDistance = 40;
// The distance (and lower than it) at which the sensor is triggered (in centimeters)
//
int duration;
int distance;

void setup() {
  pinMode(ledPin, OUTPUT);
  pinMode(trigPin, OUTPUT);
  pinMode(echoPin, INPUT);
}

void loop() {
  digitalWrite(trigPin, LOW);
  digitalWrite(trigPin, HIGH);
  delay(1);
  digitalWrite(trigPin, LOW);
  duration = pulseIn(echoPin, HIGH);
  distance = duration * 0.034 / 2;
  if (distance <= trigDistance) {
    digitalWrite(ledPin, HIGH);
    delay(ledOnTime);
    digitalWrite(ledPin, LOW);
  }
  delay(100);
}

```

# Answer
I would say the way to go is using non-blocking code with `millis()`. Look into the `BlinkWithoutDelay` example, that comes with the Arduino IDE. It doesn't use `delay()`, which is considered bad coding practice, since it is just busy waiting. Nothing else can happen during a delay, except for interrupts. Instead of waiting it is better to regularily check the clock, if it is time to do something (much like you would do in real life for example for baking a pizza).

The clock is provided by `millis()`, which returns the number of milliseconds since startup. Below you see the `BlinkWithoutDelay`example. The variable `interval` controls the blink frequency. If you remove the `const` keyword before it and change it according to the measurements from the ultrasonic sensor, you will get a changing blinking frequency with changing distance.

Try to combine the codes into one. Remove all `delay()` calls, except for the `delay(1)` (it is needed to trigger the ultrasonic sensor and it is small enough to not matter greatly).

```
const int ledPin =  LED_BUILTIN;// the number of the LED pin

// Variables will change:
int ledState = LOW;             // ledState used to set the LED

// Generally, you should use "unsigned long" for variables that hold time
// The value will quickly become too large for an int to store
unsigned long previousMillis = 0;        // will store last time LED was updated

// constants won't change:
const long interval = 1000;           // interval at which to blink (milliseconds)

void setup() {
  // set the digital pin as output:
  pinMode(ledPin, OUTPUT);
}

void loop() {
  // here is where you'd put code that needs to be running all the time.

  // check to see if it's time to blink the LED; that is, if the difference
  // between the current time and last time you blinked the LED is bigger than
  // the interval at which you want to blink the LED.
  unsigned long currentMillis = millis();

  if (currentMillis - previousMillis >= interval) {
    // save the last time you blinked the LED
    previousMillis = currentMillis;

    // if the LED is off turn it on and vice-versa:
    if (ledState == LOW) {
      ledState = HIGH;
    } else {
      ledState = LOW;
    }

    // set the LED with the ledState of the variable:
    digitalWrite(ledPin, ledState);
  }
}

```

The rest is up to you. If you need more information about the `BlinkWithoutDelay` example, you should google it. There are tons of tutorials. This is a great coding excerise, so have fun :)
> 1 votes

# Answer
**step 1**: define your MIN\_DISTANCE, MAX\_DISTANCE

**step 2**: get distance from sensor

**step 3**: rescale the distance value to a value in between 0 and 255

**step 4**: fade led according to the rescaled value.

Note that: you should not use delay() to blink LED. Use analogWrite() instead. See the example. We can change frequency of PWM to make LED from fading to blinking by using setPwmFrequency() function
> 0 votes

---
Tags: arduino-uno
---


# Question
Title: Having trouble figuring out CTC on Timer 1 with ATTiny85
I'm using Timer1 on the Attiny85 clocked at 1MHz to toggle an LED every 1 second. However, I'm having some issues regarding prescaler and OSC value selection.

I'm using this formula, which I found in the datasheet for the Attiny.

```
fOCnx = fclk/(2*N*(1+OCRnx))

```

N = Prescaler
I'm taking fOCnx = 0.5Hz as I want a square wave
So based on the above formula, I tried the following cases

1. N = 2048, OCR1C = 243
2. N = 4096, OCR1C = 122
3. N = 8192, OCR1C = 61
4. N = 16384, OCR1C = 30

The LED toggles after an interval of 1s for cases 3 and 4. However, for cases 1 and, it seems to toggle after 2 seconds. Can anyone tell me why this is happening? Eventually, I want to use this to time data acquisition from a sensor I have so I need to be accurate.

Here's my code

```
#include <SoftwareSerial.h>

int ledPin = 1;
int state = 0;

SoftwareSerial ser(3, 4);
void setup() {
  // put your setup code here, to run once:
  TCCR1 |= 0x8F;
  OCR1C = 30;
  TIMSK = (1 << OCIE1A);
  pinMode(ledPin, OUTPUT);
  ser.begin(9600);
}

ISR(TIMER1_COMPA_vect)
{
  state = !state;
  digitalWrite(ledPin, state);
  ser.println(state);
}

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

```

# Answer
> 2 votes
The only explanation I have is, that the Software serial switch off the interrupts globally when it operates (`print`). If interrupts are locked when the timer completes, you loose a tick. It does not explain the different behavior of the four value pairs, but there are some issues reported in a german forum. They did not find an answer, but the assumed it depends on the 'delay()' function, that is used for the software serial and the fact that the interrupts are locked to make the delay function more exact.

If you want to be sure, you can try this by completely removing the Software Serial from your program. If you make the values switchable by e.g. a button press you can change it without having to reload the program. Then it's easier to see different blinking intervals.

```
int ledPin = 1;
int state = 0;

int regValues[] = { 0x8f, 0x8e, 0x8d, 0x8c };
int cntValues[] = { 30, 61, 122, 243 };

const int buttonPin = 2;
int buttonState = LOW;

long lastDebounceTime = 0;
long debounceDelay = 80;
int lastButtonState = LOW;

int pairIndex = 0;

void setup()
{
  TCCR1 = regValues[ pairIndex ];
  OCR1C = cntValues[ pairIndex ];

  TIMSK = (1 << OCIE1A);

  pinMode(ledPin, OUTPUT);
  pinMode(buttonPin, INPUT);
}

ISR(TIMER1_COMPA_vect)
{
  state = !state;
  digitalWrite(ledPin, state);
}

void loop()
{
  int reading = digitalRead(buttonPin);

  if (reading != lastButtonState)
  {
    lastDebounceTime = millis();
  }

  if ( (millis() - lastDebounceTime) > debounceDelay)
  {
   if (reading != buttonState)
   {
      buttonState = reading;

      if (buttonState == HIGH)
      {
        if ( ++pairIndex > 3 )
        {
          pairIndex = 0;
        }

        TCCR1 = regValues[ pairIndex ];
        OCR1C = cntValues[ pairIndex ];
      }

    }

  }

}

```

I wrote this code without having a attiny to testing it. So hopefully all is correct. If you would try it, can you please report any errors, so I can correct them?

---
Tags: arduino-uno, arduino-ide, timers, attiny, attiny85
---


# Question
Title: I2C code working on Mega 2560 but not on Uno and nano
I have recently purchased this Heart rate sensor and was trying to make it work. I used this MAX30100 library I found on Github. For some reason when I use any of the given examples, they seem to work well when I use a Mega2560 I have but not on the Uno or Nano. Does this have to do with the processor? I don't think so because the README on Github mentions that they tested it on an Uno. But if it is so, how could I change the code to make it work with the Uno and nano?

Example Code I used:

```
// This example can be used to test connectivity and operation of the sensor
// check the README file on the repo's root for a troubleshooting guide in casem
// any of the tests running fail

#include <Wire.h>
#include "MAX30100.h"

MAX30100 sensor;

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

    Serial.print("Initializing MAX30100..");

    if (!sensor.begin()) {
        Serial.print("FAILED: ");

        uint8_t partId = sensor.getPartId();
        if (partId == 0xff) {
            Serial.println("I2C error");
        } else {
            Serial.print("wrong part ID 0x");
            Serial.print(partId, HEX);
            Serial.print(" (expected: 0x");
            Serial.println(EXPECTED_PART_ID, HEX);
        }
        // Stop here
        for(;;);
    } else {
        Serial.println("Success");
    }

    Serial.print("Enabling HR/SPO2 mode..");
    sensor.setMode(MAX30100_MODE_SPO2_HR);
    Serial.println("done.");

    Serial.print("Configuring LEDs biases to 50mA..");
    sensor.setLedsCurrent(MAX30100_LED_CURR_50MA, MAX30100_LED_CURR_50MA);
    Serial.println("done.");

    delay(1000);

    Serial.print("Lowering the current to 7.6mA..");
    sensor.setLedsCurrent(MAX30100_LED_CURR_7_6MA, MAX30100_LED_CURR_7_6MA);
    Serial.println("done.");

    delay(1000);

    Serial.print("Shutting down..");
    sensor.shutdown();
    Serial.println("done.");

    delay(1000);

    Serial.print("Resuming normal operation..");
    sensor.resume();
    delay(500);
    Serial.println("done.");

    uint32_t tsTempSampStart = millis();
    Serial.print("Sampling die temperature..");
    sensor.startTemperatureSampling();
    while(!sensor.isTemperatureReady()) {
        if (millis() - tsTempSampStart > 1000) {
            Serial.println("ERROR: timeout");
            // Stop here
            for(;;);
        }
    }

    float temperature = sensor.retrieveTemperature();
    Serial.print("done, temp=");
    Serial.print(temperature);
    Serial.println("C");

    if (temperature < 5) {
        Serial.println("WARNING: Temperature probe reported an odd value");
    } else {
        Serial.println("All test pass.");
    }

    Serial.println();
    Serial.println("Press any key to go into sampling loop mode");
    while (!Serial.available());

    sensor.resetFifo();
}

void loop()
{
    uint16_t ir, red;

    sensor.update();

    while (sensor.getRawValues(&ir, &red)) {
        Serial.print("IR=");
        Serial.print(ir);
        Serial.print(" RED=");
        Serial.println(red);
    }
}

```

# Answer
> 1 votes
I added pull-up resistors to the board and it started working. Turns out that the boards weren't well designed and the I2C lines were pulled up to 1.8V instead of Vin. By removing the pull-ups and adding pull-ups to Vin, the circuit started functioning. The circuit worked with Mega because it has in-built Pull-up Resistors.

---
Tags: arduino-uno, arduino-mega, arduino-nano, i2c
---


title: DS3231 + button to trigger light

text:
# Question
Title: DS3231 + button to trigger light
please can someone help me with code, i want to have automatic trigger on specific hour, also i want to have button switch if needed, in my code i can press the button to trigger light relay, but my specific time trigger just flash at start time and does nothing, here is code:

```
#include <LiquidCrystal_I2C.h>
#include <DS3231.h>
LiquidCrystal_I2C lcd(0x27, 2, 1,0,4,5,6,7,3, POSITIVE);
DS3231  rtc(SDA, SCL);
Time t;

const int OnSec = 30;
const int OffSec = 5;
int relay_3 = 5 ;

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

 pinMode(relay_3,OUTPUT);
 pinMode(8, INPUT_PULLUP);
}

void loop() {
  int button_4 = digitalRead(8);
  t = rtc.getTime();
  lcd.setCursor(0,1);
  lcd.print(rtc.getTimeStr());

  if(t.sec == OnSec)                                  //if is hh.mm.30 - just for 1 sec trigger relay
  {
  digitalWrite(5,HIGH);
  }
    else if(t.sec == OffSec)                         //if is hh.mm.05 - release relay
  {
  digitalWrite(5,LOW);
  }
      else if (button_4 == HIGH)                     //if button is pressed - trigger relay
  {
  digitalWrite(5,HIGH);
  }
        else
  {
  digitalWrite(5,LOW);
  }

  lcd.clear();
}

```

i would be gratefull for any advice :)

# Answer
The else case is executed every time the other `if` and `else if` conditions are **not** true. That means if it is not 5 sec and not 30 sec and no button is pressed, the relay is switched off.

To achieve what you want is not that easy, because you have to synchronize button press and button release with the timer actions. First you must specify what you exactly want to do. e.g What happens if you have already pressed the button and release it in the time interval between 30 and 5. Releasing the button would switch off the light but should it stay on because you are within the on-time? This is just an example of what to think about.

I wrote a little code for fun doing the things as I would do it:

```
#include <LiquidCrystal_I2C.h>
#include <DS3231.h>
LiquidCrystal_I2C lcd(0x27, 2, 1,0,4,5,6,7,3, POSITIVE);
DS3231  rtc( SDA, SCL );
Time t;

const int OnSec = 30;
const int OffSec = 5;
int relay_3 = 5;

int timerPhase = -1;
int relayState = LOW;

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

 pinMode( relay_3, OUTPUT );
 pinMode( 8, INPUT_PULLUP );
}

void loop()
{
  t = rtc.getTime( );

  int button_4 = digitalRead( 8 );

  lcd.setCursor( 0, 1 );
  lcd.print( rtc.getTimeStr( ) );

  // this only works if the off time is
  // less than the on time. (OffSec < OnSec)
  timerPhase = ( (t.sec > OffSec) && ( t.sec < OnSec ) ) ? 0 : 1;

  if ( button_4 == HIGH )
  {
    // a button overrides the timer phase
    relayState = HIGH;
  }
  else
  {
    if ( timerPhase == 0 )
    {
      relayState = LOW;
    }
    else
    {
      relayState = HIGH;
    }
  }

  digitalWrite( relay_3, relayState );

  lcd.clear();
}

```

I could not try the code because I don't know which libraries you used and therefor got compiler errors. So there might be syntax errors in my code but I hope I wrote correct code. It would be nice if you report errors here, if you find one/some ;-).

The line

```
timerPhase = ( (t.sec > OffSec) && ( t.sec < OnSec ) ) ? 0 : 1;

```

uses a ternary operator. It means if the condition `( (t.sec > OffSec) && ( t.sec < OnSec ) )` is `true`, take the first alternative `0` and assign it to the variable `timerPhase`, if it is `false` choose the second alternative '1'.
> 1 votes

---
Tags: arduino-uno, programming, arduino-ide, timers, button
---


# Question
Title: Is it possible to connect from esp8266 module over HTTPS protocol?
Before I will implementing some server application for Arduino client I should know:

Is it possible to connect from esp8266 module to end-point over HTTPS protocol?

Any links of tutorials are welcome.

Thank in advance.

# Answer
Yes it's possible. Try this one tutorial. https://circuits4you.com/2019/01/10/esp8266-nodemcu-https-secured-get-request/
> 1 votes

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


# Question
Title: Using Arrays and LED's to represent Piano Scales
I am trying to use addressable LED's to show various piano scales using the semi notes formula for each scale as an array and an input to indicate the starting note.

```
int MajorScale[] = {2,2,1,2,2,2,1}; //represents the semi notes in a major scale
int t= 8 //represents the led number that represent the first C on the keyboard

```

The following leds should light up -

(8, 8+2, 8+2+2, 8+2+2+1, 8+2+2+1+2, 8+2+2+1+2+2, 8+2+2+1+2+2+2 , 8+2+2+1+2+2+2+1) // This is first C Major Scale on the Piano

so.. (8,10,12,13,15,17,19) // This is first C Major Scale on the Piano where 8 is the first c

Then light up all the other C Major scales available on the piano limited by the number of keys on the piano in this case 76 keys

As there are 12 notes for each octave , add this to the array

if i take just the C note

8, 8+12, 8+12+12 ,8+12+12+12, 8+12+12+12+12 etc

My code so far just lights up the semitone that i set up in the array

```
enter code here
#include "FastLED.h"
#define DATA_PIN 5
#define NUM_LEDS 76
#define BRIGHTNESS 10
CRGB leds[NUM_LEDS];
int MajorScale[] = {2,2,1,2,2,2,1};
int delayValue = 1000;

void setup() {
Serial.begin(9600); // open the serial port at 9600 bps:
FastLED.addLeds<WS2812B, DATA_PIN, GRB>(leds, NUM_LEDS);
FastLED.setBrightness(BRIGHTNESS);
FastLED.clear();
}

void loop() {
for(int i = 0; i <=6; i++)
{
    leds[MajorScale[i]] = CRGB::BlueViolet;
    FastLED.show();
     delay(delayValue);

}

FastLED.clear();
}

```

# Answer
Your current code will not show all notes of a scale. Only the notes at 1 and 2 will light up, since you don't sum up the numbers, that you have stored in `MajorScale`. But I think it is not a great idea to sum them up programatically, since this is a constant and you don't win much by representing the data this way. Instead you should directly initiate the `MajorScale` variable with the summed up values:

```
int MajorScale[] = {0, 2, 4, 5, 7, 9, 11};

```

Then you can enclose your for loop with another for loop, that adds an offset corresponding to the octave:

```
for(int j=0; j<NUM_LEDS; j+=12){
    for(int i=0; i<=6 && MajorScale[i]+j<NUM_LEDS;i++){
        leds[8+MajorScale[i]+j] = CRGB::BlueViolet;
        FastLED.show();
        delay(delayvalue);
    }
}

```

So we set the LED number `8+MajorScale[i]+j`. 8 for the offset to C, `MajorScale[i]` as the position of the note in the current octave and `j` for the offset of the current octave relative to the C.

Note, that this is not tested in any way.
> 1 votes

---
Tags: arduino-mega, array
---


# Question
Title: How can I clear the memory of my Arduino in this case?
I have made a code using involving HID control. But it seems that I messed up, but I can't upload a new sketch(nor edit the wrong code), because my Arduino is constantly doing things like Ctrl+Alt+Delete, Alt+F4... etc. It seems that the only way is erasing the code in the memory, but how can I do so?

# Answer
> 1 votes
1. Do the "button dance" - hold the Arduino in reset, releasing just you see the download start in the IDE. This may (will!) take a little practice to get just the right timing.

or

2. Use an external programmer connected to the ICSP connector. This could be a commercially made one, a DIY, or another Uno programmed and connected as an ICSP programmer. How-to's abound on the web.

---
Tags: arduino-leonardo, keyboard, reset
---


# Question
Title: no matching function to call for SoftwareSerial::SoftwareSerial(int&,int&)? How to rectify this problem
```
#include <LiquidCrystal.h>

#include <SoftwareSerial.h>

float pulse = 0;

float temp = 0;

SoftwareSerial ser(9,10);

String apiKey = "U5AGYVQT5JRJPSDR";

//  Variables

int pulsePin = A0;                 // Pulse Sensor purple wire connected to analog pin 0

int blinkPin = 7           ;                // pin to blink led at each beat

int fadePin = 8;                  // pin to do fancy classy fading blink at each beat

int fadeRate = 0;                 // used to fade LED on with PWM on fadePin

LiquidCrystal lcd(13, 12, 6, 5, 4, 3);

// Volatile Variables, used in the interrupt service routine!

volatile int BPM;                   // int that holds raw Analog in 0. updated every 2mS

volatile int Signal;                // holds the incoming raw data

volatile int IBI = 600;             // int that holds the time interval between beats! Must be seeded!

volatile boolean Pulse = false;     // "True" when User's live heartbeat is detected. "False" when not
 a "live beat".

volatile boolean QS = false;        // becomes true when Arduoino finds a beat.

// Regards Serial OutPut  -- Set This Up to your needs

static boolean serialVisual = true;   // Set to 'false' by Default.  Re-set to 'true' to see Arduino
Serial Monitor ASCII Visual Pulse

volatile int rate[10];                      // array to hold last ten IBI values

volatile unsigned long sampleCounter = 0;          // used to determine pulse timing

volatile unsigned long lastBeatTime = 0;           // used to find IBI

volatile int P = 512;                      // used to find peak in pulse wave, seeded

volatile int T = 512;                     // used to find trough in pulse wave, seeded

volatile int thresh = 525;                // used to find instant moment of heart beat, seeded

volatile int amp = 100;                   // used to hold amplitude of pulse waveform, seeded

volatile boolean firstBeat = true;        // used to seed rate array so we startup with reasonable BPM

volatile boolean secondBeat = false;      // used to seed rate array so we startup with reasonable BPM

void setup()

{

  lcd.begin(16, 2);

  pinMode(blinkPin,OUTPUT);         // pin that will blink to your heartbeat!

  pinMode(fadePin,OUTPUT);          // pin that will fade to your heartbeat!

  Serial.begin(115200);             // we agree to talk fast!

  interruptSetup();                 // sets up to read Pulse Sensor signal every 2mS

                                    // IF YOU ARE POWERING The Pulse Sensor AT VOLTAGE LESS THAN THE BOARD VOLTAGE,

                                    // UN-COMMENT THE NEXT LINE AND APPLY THAT VOLTAGE TO THE A-REF PIN

                                    //   analogReference(EXTERNAL);

  lcd.clear();

  lcd.setCursor(0,0);

  lcd.print("Engineers Garage");

  ser.begin(9600);

  ser.println("AT");

  delay(1000);

  ser.println("AT+GMR");

  delay(1000);

  ser.println("AT+CWMODE=3");

  delay(1000);

  ser.println("AT+RST");

  delay(5000);

  ser.println("AT+CIPMUX=1");

  delay(1000);

  String cmd="AT+CWJAP="EngineersGarage","egP@$$w0rd?"";

  ser.println(cmd);

  delay(1000);

  ser.println("AT+CIFSR");

  delay(1000);

}

//  Where the Magic Happens

void loop()

{

   serialOutput();

  if (QS == true) // A Heartbeat Was Found

    {

      // BPM and IBI have been Determined

      // Quantified Self "QS" true when arduino finds a heartbeat

      fadeRate = 255; // Makes the LED Fade Effect Happen, Set 'fadeRate' Variable to 255 to fade LED
 with pulse

      serialOutputWhenBeatHappens(); // A Beat Happened, Output that to serial.

      QS = false; // reset the Quantified Self flag for next time

    }

  ledFadeToBeat(); // Makes the LED Fade Effect Happen

  delay(20); //  take a break

  read_temp();

  esp_8266();

}

void ledFadeToBeat()

{

   fadeRate -= 15;                         //  set LED fade value

   fadeRate = constrain(fadeRate,0,255);   //  keep LED fade value from going into negative numbers!

   analogWrite(fadePin,fadeRate);          //  fade LED

}

void interruptSetup()

{

  // Initializes Timer2 to throw an interrupt every 2mS.

  TCCR2A = 0x02;     // DISABLE PWM ON DIGITAL PINS 3 AND 11, AND GO INTO CTC MODE

  TCCR2B = 0x06;     // DON'T FORCE COMPARE, 256 PRESCALER

  OCR2A  = 0X7C;      // SET THE TOP OF THE COUNT TO 124 FOR 500Hz SAMPLE RATE

  TIMSK2 = 0x02;     // ENABLE INTERRUPT ON MATCH BETWEEN TIMER2 AND OCR2A

  sei();             // MAKE SURE GLOBAL INTERRUPTS ARE ENABLED

}

void serialOutput()

{   // Decide How To Output Serial.

 if (serialVisual == true)

  {

     arduinoSerialMonitorVisual('-', Signal);   // goes to function that makes Serial Monitor Visualizer

  }

 else

  {

      sendDataToSerial('S', Signal);     // goes to sendDataToSerial function

   }

}

void serialOutputWhenBeatHappens()

{

 if (serialVisual == true) //  Code to Make the Serial Monitor Visualizer Work

   {

     Serial.print("*** Heart-Beat Happened *** ");  //ASCII Art Madness

     Serial.print("BPM: ");

     Serial.println(BPM);

     lcd.clear();

     lcd.print("BPM: ");

     lcd.print(BPM);

   }

 else

   {

     sendDataToSerial('B',BPM);   // send heart rate with a 'B' prefix

     sendDataToSerial('Q',IBI);   // send time between beats with a 'Q' prefix

   }

}

void arduinoSerialMonitorVisual(char symbol, int data )

{

  const int sensorMin = 0;      // sensor minimum, discovered through experiment

  const int sensorMax = 1024;    // sensor maximum, discovered through experiment

  int sensorReading = data; // map the sensor range to a range of 12 options:

  int range = map(sensorReading, sensorMin, sensorMax, 0, 11);

  // do something different depending on the

  // range value:

  switch (range)

  {

    case 0:

      Serial.println("");     /////ASCII Art Madness

      break;

    case 1:

      Serial.println("---");

      break;

    case 2:

      Serial.println("------");

      break;

    case 3:

      Serial.println("---------");

      break;

    case 4:

      Serial.println("------------");

      break;

    case 5:

      Serial.println("--------------|-");

      break;

    case 6:

      Serial.println("--------------|---");

      break;

    case 7:

      Serial.println("--------------|-------");

      break;

    case 8:

      Serial.println("--------------|----------");

      break;

    case 9:

      Serial.println("--------------|----------------");

      break;

    case 10:

      Serial.println("--------------|-------------------");

      break;

    case 11:

      Serial.println("--------------|-----------------------");

      break;

  }

}

void sendDataToSerial(char symbol, int data )

{

   Serial.print(symbol);

   Serial.println(data);

}

ISR(TIMER2_COMPA_vect) //triggered when Timer2 counts to 124

{

  cli();                                      // disable interrupts while we do this

  Signal = analogRead(pulsePin);              // read the Pulse Sensor

  sampleCounter += 2;                         // keep track of the time in mS with this variable

  int N = sampleCounter - lastBeatTime;       // monitor the time since the last beat to avoid noise

                                              //  find the peak and trough of the pulse wave

  if(Signal < thresh && N > (IBI/5)*3) // avoid dichrotic noise by waiting 3/5 of last IBI

    {

      if (Signal < T) // T is the trough

      {

        T = Signal; // keep track of lowest point in pulse wave

      }

    }

  if(Signal > thresh && Signal > P)

    {          // thresh condition helps avoid noise

      P = Signal;                             // P is the peak

    }                                        // keep track of highest point in pulse wave

  //  NOW IT'S TIME TO LOOK FOR THE HEART BEAT

  // signal surges up in value every time there is a pulse

  if (N > 250)

  {                                   // avoid high frequency noise

    if ( (Signal > thresh) && (Pulse == false) && (N > (IBI/5)*3) )

      {

        Pulse = true;                               // set the Pulse flag when we think there is a pulse

        digitalWrite(blinkPin,HIGH);                // turn on pin 13 LED

        IBI = sampleCounter - lastBeatTime;         // measure time between beats in mS

        lastBeatTime = sampleCounter;               // keep track of time for next pulse

        if(secondBeat)

        {                        // if this is the second beat, if secondBeat == TRUE

          secondBeat = false;                  // clear secondBeat flag

          for(int i=0; i<=9; i++) // seed the running total to get a realisitic BPM at startup

          {

            rate[i] = IBI;

          }

        }

        if(firstBeat) // if it's the first time we found a beat, if firstBeat == TRUE

        {

          firstBeat = false;                   // clear firstBeat flag

          secondBeat = true;                   // set the second beat flag

          sei();                               // enable interrupts again

          return;                              // IBI value is unreliable so discard it

        }

      // keep a running total of the last 10 IBI values

      word runningTotal = 0;                  // clear the runningTotal variable

      for(int i=0; i<=8; i++)

        {                // shift data in the rate array

          rate[i] = rate[i+1];                  // and drop the oldest IBI value

          runningTotal += rate[i];              // add up the 9 oldest IBI values

        }

      rate[9] = IBI;                          // add the latest IBI to the rate array

      runningTotal += rate[9];                // add the latest IBI to runningTotal

      runningTotal /= 10;                     // average the last 10 IBI values

      BPM = 60000/runningTotal;               // how many beats can fit into a minute? that's BPM!

      QS = true;                              // set Quantified Self flag

      // QS FLAG IS NOT CLEARED INSIDE THIS ISR

      pulse = BPM;

    }

  }

  if (Signal < thresh && Pulse == true)

    {   // when the values are going down, the beat is over

      digitalWrite(blinkPin,LOW);            // turn off pin 13 LED

      Pulse = false;                         // reset the Pulse flag so we can do it again

      amp = P - T;                           // get amplitude of the pulse wave

      thresh = amp/2 + T;                    // set thresh at 50% of the amplitude

      P = thresh;                            // reset these for next time

      T = thresh;

    }

  if (N > 2500)

    {                           // if 2.5 seconds go by without a beat

      thresh = 512;                          // set thresh default

      P = 512;                               // set P default

      T = 512;                               // set T default

      lastBeatTime = sampleCounter;          // bring the lastBeatTime up to date

      firstBeat = true;                      // set these to avoid noise

      secondBeat = false;                    // when we get the heartbeat back

    }

  sei();                                   // enable interrupts when youre done!

}// end isr

void esp_8266()

{

   // TCP connection AT+CIPSTART=4,"TCP","184.106.153.149",80

    String cmd = "AT+CIPSTART=4,"TCP","";

    cmd += "184.106.153.149"; // api.thingspeak.com

    cmd += "",80";

    ser.println(cmd);

    Serial.println(cmd);

    if(ser.find("Error"))

    {

      Serial.println("AT+CIPSTART error");

      return;

    }

  // prepare GET string GET https://api.thingspeak.com/update?api_key=LHAG4NSIYJ5UWS6U&field1=0rnrn

  String getStr = "GET /update?api_key=";

  getStr += apiKey;

  getStr +="&field1=";

  getStr +=String(temp);

  getStr +="&field2=";

  getStr +=String(pulse);

  getStr += "rnrn";

  // send data length

  cmd = "AT+CIPSEND=4,";

  cmd += String(getStr.length());

  ser.println(cmd);

  Serial.println(cmd);

  delay(1000);

  ser.print(getStr);

  Serial.println(getStr);

 //thingspeak needs 15 sec delay between updates

  delay(3000);

}

void read_temp()

{

  int temp_val =  analogRead(A1);

  float mv = (temp_val/1024.0)*5000;

  float cel = mv/10;

  temp = (cel*9)/5 + 32;

}

```

# Answer
The sketch in the question is not for NodeMCU. It is for Arduino with esp8266 wired on pins 9 and 10. But the error in title is a current error for esp8266 Arduino boards package 2.6.0. The EspSoftwareSerial bundled with the esp8266 Arduino boards package version 2.6.0 has a compatibility breaking change.

The problem was immediately reported and the EspSoftwareSerial maintainer added the legacy API back to EspSoftwareSerial. The fixed version will be available with esp8266 boards package 2.6.1, which will be available soon because of multiple problems with 2.6.0.
> 2 votes

---
Tags: esp8266, softwareserial
---


# Question
Title: Measuring 12 V via voltage divider: choosing the right resistors
I want to measure a 9 V battery via one of the analog input ports of my Arduino Nano. From all the schemes of this great answer, I choose the simplest one, the voltage divider. Assuming the maximum input voltage to be 12 V (just to be safe) and maximum divider's output voltage to be 5 V, I've solved it against R₂:R₁ proportion. It turns out that R₂:R₁ = 5:7.

simulate this circuit – Schematic created using CircuitLab

With the values above, the input of A0 pin will be exactly 5 V.

The problem is that it could be any values. 5 Ω and 7 Ω or 5 MΩ and 7 MΩ!

I understand, that there should be another equation to take into account that will give me the values of those two resistors. Another brilliant answer demonstrates, that the values depend on the current I want to flow through the branches:

> So the point is when determining the resistance of the resistors, we should take into account the input resistance of the load and the two voltage divider resistors should be as small as possible.
>
> On the other hand, let's compare the current going through the divider in the circuit with large resistors on the divider and the circuit with small resistors on the divider. As you can see, the large resistors have current of just 2.5 μA going through them and the small resistors have current of 25 mA. The point here is that the current is wasted by the voltage divider and if this was for example part of a battery operated device, it would have a negative impact on the battery life. So the resistors should be as large as possible in order to lower the wasted current.

9 V batteries are known to have a little of energy canned inside, with the most popular 6LR61 having only about 550 mA·h. I do not want to waste it on heating the resistors, so, probably, I need to use large resistors. But how large? Too large R₁ will let only a little current to flow to the A0 pin and I've read somewhere that small currents may lead to `analogRead` measurement errors (underestimations?) due to ADC's internal capacitor.

Trying to find the right answer, I've read on the Arduino's forum that:

> The ATmega328P datasheet has this info way in the back: Table 28-16 (page 328). The analog input resistance is claimed to be 100 Mohms.
>
> During an actual sample, the input resistance is temporarily a lot lower as the sampling capacitor is charged up so **it is recommended that whatever you connect to the A/D have an output impedance of 10k or less for best accuracy**.

And here, I am stuck. I understand that **I am connecting a voltage divider to the A/D, but what is it's "output impedance"?** It should depend on R₁ and R₂ somehow, and solving that equation (`F(R₁, R₂) == 10 000`) will give me the exact value…

P.S. I saw some cunning schemes in the Internet with capacitors, diodes and op-amps (everybody say it's super easy and safe to use them for this task), but, please:

* I am just trying to understand the basics and making my first steps with electronics.
* The device I'm making should be lightweight and compact (although I should be able to compose it without any PCB magic). Two resistors seems to be fine.
* I'm going to read the voltage only once when the device is turned on, so I don't actually need super-fast op-amp's speed.
* I'll try not to plug negative voltage, so I do not need a protection. Yet.

# Answer
> 3 votes
What you are looking for is called the Thévenin equivalent source. For the schematic you are showing, and assuming you can neglect the output resistance of the battery itself, the output resistance of the voltage divider is the same as the two resistors in parallel. If you want the maximum allowed resistance (minimum current) you have then to solve:

1/R1 \+ 1/R2 = 1/(10 kΩ)
R2 / (R1 \+ R2) = 5/12

which gives:

R1 = 12/5 × 10 kΩ = 24 kΩ
R2 = 12/7 × 10 kΩ ≈ 17.1 kΩ

You can then round the values down to the closest standard values, taking care that the rounding does not impose more than 5 V on the analog pin. For example, if you restrict yourself to the E6 series, you could choose

R1 = 22 kΩ
R2 = 15 kΩ

which would give you a Thévenin equivalent output resistance of 8.9 kΩ, and a maximum output voltage of 4.86 V.

---
Tags: analogread, voltage-divider
---


title: SD writing problem

text:
# Question
Title: SD writing problem
I have an Arduino code for logging sensor data, time and date. Then I store all the data in the SD card and then I will send the sensor value to another node by using Lora. but I can't write the data in the SD card. Please help me to solve this problem. The code is also attached.

```
#include <RHReliableDatagram.h>
#include <RH_RF95.h>
#include "RTClib.h"
#include <SPI.h>
#include <SD.h>

RTC_DS1307 rtc;
File myFile;

#define node_address 12
uint8_t gateway_address = 11;
const int sensor_pin = A1;
float level;

/* Chip selection */
const int CS1 = 8;/*SD Card*/
const int CS2 = 10;/*LoRa*/

/* Configure LoRa driver */
RH_RF95 driver(10,2);
RHReliableDatagram manager(driver,node_address);

void setup () {
  pinMode(sensor_pin, INPUT);
  pinMode(CS1,OUTPUT);
  pinMode(CS2,OUTPUT);
//  SPI.begin();`
  /*--------Serial port connection setup--------*/
  Serial.begin(9600);

  /*----------RTC Initialization----------*/
  Serial.println(F("Initializing RTC...!"));
  if (! rtc.begin()) {
    Serial.println(F("Couldn't find RTC"));
  }
  if (! rtc.isrunning()) {
    Serial.println(F("RTC is NOT running!"));
//    rtc.adjust(DateTime(2019, 11, 12, 12, 32, 0)); // (Year,Month,Date,Hour,Min,Sec)
  }

  /*----------SD CARD Initialization----------*/
  digitalWrite(CS2,HIGH);
  delay(500);
  digitalWrite(CS1,LOW);
  Serial.println(F("Initializing SD card..."));
  if (!SD.begin(CS1)) {
    Serial.println(F("initialization of SD Card is failed!"));
    return;
  }
  Serial.println(F("Initialization of SD Card is done."));
  /*----------LoRa Initialization----------*/
  digitalWrite(CS1,HIGH);
  delay(500);
  digitalWrite(CS2,LOW);
  if (manager.init())
  {
    Serial.println(F("LoRa Successfully Initialised "));
  } else {
    Serial.println(F("LoRa initialization failed"));
  }
  driver.setFrequency(433.0);
  driver.setTxPower(14,false);
  Serial.println();
}

void loop () {
  DateTime now = rtc.now();
  /*----------Date----------*/
  Serial.print(now.year(), DEC);
  Serial.print('/');
  Serial.print(now.month(), DEC);
  Serial.print('/');
  Serial.print(now.day(), DEC);
  Serial.print(',');
  /*----------Time----------*/
  Serial.print(now.hour(), DEC);
  Serial.print(':');
  Serial.print(now.minute(), DEC);
  Serial.print(':');
  Serial.print(now.second(), DEC);
  Serial.println();

  /*----------SD card----------*/
  digitalWrite(CS2,HIGH);
  delay(500);
  digitalWrite(CS1,LOW);
  delay(100);
  myFile = SD.open("test.txt", FILE_WRITE);
  if (myFile) {
    /*----------Saving Date----------*/
    myFile.print(now.year(), DEC);
    myFile.print('/');
    myFile.print(now.month(), DEC);
    myFile.print('/');
    myFile.print(now.day(), DEC);
    myFile.print(',');
    /*----------Saving Time----------*/
    myFile.print(now.hour(), DEC);
    myFile.print(':');
    myFile.print(now.minute(), DEC);
    myFile.print(':');
    myFile.print(now.second(), DEC);
    myFile.println(',');
    level = analogRead(sensor_pin);
    myFile.print(level);
    myFile.println();
    myFile.close();
  } else {
    Serial.println("Error opening test.txt");
  }
  delay(500);
  digitalWrite(CS1,HIGH);
  delay(500);
  digitalWrite(CS2,LOW);
  char data[RH_RF95_MAX_MESSAGE_LEN];
  sprintf(data,"$%d#%d",node_address,level);
  Serial.print("Level transferred is ");
  Serial.println(data);
  Serial.println(sizeof(data));
  if(!manager.sendtoWait((uint8_t*)data,sizeof(data),gateway_address))
  {
    Serial.println("Gateway offline");
  }
  delay(500);
}

```

# Answer
> 2 votes
You should not manually control the SD card's CS pin. By doing so you are confusing both the library and the SD card.

There is a special operation with SD cards in "SPI" mode that isn't part of the SPI standard as part of the initialization routine whereby the master (the Arduino) must send at least 72 clock pulses to the card *with the CS pin held HIGH*.

By manually setting the CS pin LOW you are breaking that.

There is no call for you to ever do anything for the CS pin other than tell the library what it is - the library does everything else for you. So remove all references to `digitalWrite(CS1, ...)` from your code.

---
Tags: arduino-nano, spi, sd-card
---


# Question
Title: Help with Stair Lighting using HC-SR04 sensor and WS2812 LED Strip
Excuse my naivete in this as I am very new to Arduino and the programming of. I am trying to put together a project for stair lighting triggered by a ultrasonic sensor at the bottom of the stairs and turned off by an ultrasonic sensor at the top of the stairs and vise versa. I am using an WS2812 LED strip and have the lights travel up the stairs when going up and down when going down. I'm sure this is a project many of you have seen. I have searched the net and youtube and have found many examples of this project, none that I can find using the HC-SR04 sensor. I have managed to cobble together a code which works fine in both direction but it is intermittent in working. I'm sure it is something to do with timings as sometimes it will work fine first time but then others the sensor needs to be blocked for a couple of seconds. I would also like to add an LDR to the project so it is only active at night. If any of you can point me in the right direction I would be really grateful. I have attached the code so you can see where I am at. This is just a test code and the final project will have around 200 LEDS. Thanks

```

#include <FastLED.h>
#define trigPin_up 2
#define echoPin_up 3
#define trigPin_down 4
#define echoPin_down 5
#define LED_PIN     7
#define NUM_LEDS    13
CRGB leds[NUM_LEDS];

void setup() {

    //Set Serial
  Serial.begin(9600);

  FastLED.addLeds<WS2812, LED_PIN, GRB>(leds, NUM_LEDS);

  pinMode(trigPin_up, OUTPUT);
  pinMode(echoPin_up, INPUT);
  pinMode(trigPin_down, OUTPUT);
  pinMode(echoPin_down, INPUT);

}
 void loop(){
 if (trigPin_up, HIGH && trigPin_down, LOW);
 {
   short duration, distance;
  digitalWrite(trigPin_up, LOW);
  delayMicroseconds(2);
  digitalWrite(trigPin_up, HIGH);
  delayMicroseconds(10);
  digitalWrite(trigPin_up, LOW);
  duration = pulseIn(echoPin_up, HIGH);
  distance = (duration/2) / 29.1;

  if (distance <= 50) {
  leds[0] = CRGB(255, 225, 255);
  FastLED.show();
  delay(100);
  leds[1] = CRGB(255, 255, 255);
  FastLED.show();
  delay(100);
  leds[2] = CRGB(255, 255, 255);
  FastLED.show();
  delay(100);
  leds[3] = CRGB(255, 255, 255);
  FastLED.show();
  delay(100);
  leds[4] = CRGB(255, 255, 255);
  FastLED.show();
  delay(100);
  leds[5] = CRGB(255, 255, 255);
  FastLED.show();
  delay(100);
  leds[6] = CRGB(255, 255, 255);
  FastLED.show();
   delay(100);
   leds[7] = CRGB(255, 255, 255);
  FastLED.show();
   delay(100);
   leds[8] = CRGB(255, 255, 255);
  FastLED.show();
   delay(100);
   leds[9] = CRGB(255, 255, 255);
  FastLED.show();
   delay(100);
   leds[10] = CRGB(255, 255, 255);
  FastLED.show();
   delay(100);
   leds[11] = CRGB(255, 255, 255);
  FastLED.show();
   delay(100);
   leds[12] = CRGB(255, 255, 255);
  FastLED.show();
   delay(100);
   leds[13] = CRGB(255, 255, 255);
  FastLED.show();
  delay(100);
  }

{    short duration, distance;
  digitalWrite(trigPin_down, LOW);
  delayMicroseconds(2);
  digitalWrite(trigPin_down, HIGH);
  delayMicroseconds(10);
  digitalWrite(trigPin_down, LOW);
  duration = pulseIn(echoPin_down, HIGH);
  distance = (duration/2) / 29.1;

  if (distance <= 50) {
  leds[0] = CRGB(0, 0, 0);
  FastLED.show();
  delay(100);
  leds[1] = CRGB(0, 0, 0);
  FastLED.show();
  delay(100);
  leds[2] = CRGB(0, 0, 0);
  FastLED.show();
  delay(100);
  leds[3] = CRGB(0, 0, 0);
  FastLED.show();
  delay(100);
  leds[4] = CRGB(0, 0, 0);
  FastLED.show();
  delay(100);
  leds[5] = CRGB(0, 0, 0);
  FastLED.show();
  delay(100);
  leds[6] = CRGB(0, 0, 0);
  FastLED.show();
   delay(100);
   leds[7] = CRGB(0, 0, 0);
  FastLED.show();
   delay(100);
   leds[8] = CRGB(0, 0, 0);
  FastLED.show();
   delay(100);
   leds[9] = CRGB(0, 0, 0);
  FastLED.show();
   delay(100);
   leds[10] = CRGB(0, 0, 0);
  FastLED.show();
   delay(100);
   leds[11] = CRGB(0, 0, 0);
  FastLED.show();
   delay(100);
   leds[12] = CRGB(0, 0, 0);
  FastLED.show();
   delay(100);
   leds[13] = CRGB(0, 0, 0);
  FastLED.show();
  delay(100);
  }

else
if (trigPin_up, LOW && trigPin_down, HIGH);
  {

     short duration, distance;
  digitalWrite(trigPin_down, LOW);
  delayMicroseconds(2);
  digitalWrite(trigPin_down, HIGH);
  delayMicroseconds(10);
  digitalWrite(trigPin_down, LOW);
  duration = pulseIn(echoPin_down, HIGH);
  distance = (duration/2) / 29.1;

  if (distance <= 50) {
  leds[13] = CRGB(255, 225, 255);
  FastLED.show();
  delay(100);
  leds[12] = CRGB(255, 255, 255);
  FastLED.show();
  delay(100);
  leds[11] = CRGB(255, 255, 255);
  FastLED.show();
  delay(100);
  leds[10] = CRGB(255, 255, 255);
  FastLED.show();
  delay(100);
  leds[9] = CRGB(255, 255, 255);
  FastLED.show();
  delay(100);
  leds[8] = CRGB(255, 255, 255);
  FastLED.show();
  delay(100);
  leds[7] = CRGB(255, 255, 255);
  FastLED.show();
   delay(100);
   leds[6] = CRGB(255, 255, 255);
  FastLED.show();
   delay(100);
   leds[5] = CRGB(255, 255, 255);
  FastLED.show();
   delay(100);
   leds[4] = CRGB(255, 255, 255);
  FastLED.show();
   delay(100);
   leds[3] = CRGB(255, 255, 255);
  FastLED.show();
   delay(100);
   leds[2] = CRGB(255, 255, 255);
  FastLED.show();
   delay(100);
   leds[1] = CRGB(255, 255, 255);
  FastLED.show();
   delay(100);
   leds[0] = CRGB(255, 255, 255);
  FastLED.show();
  delay(100);
  }
{
  short duration, distance;
  digitalWrite(trigPin_up, LOW);
  delayMicroseconds(2);
  digitalWrite(trigPin_up, HIGH);
  delayMicroseconds(10);
  digitalWrite(trigPin_up, LOW);
  duration = pulseIn(echoPin_up, HIGH);
  distance = (duration/2) / 29.1;

    if (distance <= 50) {
  leds[13] = CRGB(0, 0, 0);
  FastLED.show();
  delay(100);
  leds[12] = CRGB(0, 0, 0);
  FastLED.show();
  delay(100);
  leds[11] = CRGB(0, 0, 0);
  FastLED.show();
  delay(100);
  leds[10] = CRGB(0, 0, 0);
  FastLED.show();
  delay(100);
  leds[9] = CRGB(0, 0, 0);
  FastLED.show();
  delay(100);
  leds[8] = CRGB(0, 0, 0);
  FastLED.show();
  delay(100);
  leds[7] = CRGB(0, 0, 0);
  FastLED.show();
   delay(100);
   leds[6] = CRGB(0, 0, 0);
  FastLED.show();
   delay(100);
   leds[5] = CRGB(0, 0, 0);
  FastLED.show();
   delay(100);
   leds[4] = CRGB(0, 0, 0);
  FastLED.show();
   delay(100);
   leds[3] = CRGB(0, 0, 0);
  FastLED.show();
   delay(100);
   leds[2] = CRGB(0, 0, 0);
  FastLED.show();
   delay(100);
   leds[1] = CRGB(0, 0, 0);
  FastLED.show();
   delay(100);
   leds[0] = CRGB(0, 0, 0);
  FastLED.show();
  delay(100);
  }
}

  }
}
 }
 }

```

# Answer
There are a couple things with your code which you might need to look into. Note: I'm doing this ontop of my head, so please correct me if I say something incorrect. \]

**First**, to check if values are equal, with an if-statement you'd have to use:

```
//if (trigPin_up, HIGH && trigPin_down, LOW); not like this.
if (trigPin_up== HIGH && trigPin_down== LOW) {.....} //But like this

```

Do not use the ';' because that would be then end of the statement.

**Second**, there seems to be a random '{' without any statement beforehand, at line 88.

**Extra tip** You can use for loops! So:

```
leds[0] = CRGB(255, 225, 255);
  FastLED.show();
  delay(100);
  ....
  leds[13] = CRGB(255, 255, 255);
  FastLED.show();
  delay(100);

```

becomes:

```
for (int i = 0; i <14; i++){
    leds[i] = CRGB(255, 225, 255);
  FastLED.show();
  delay(100);
  }

```

As a good exercise, could you try to clean up your code, edit it in the OP, and try if it works then?
> 2 votes

# Answer
Calvin Bootsman is right with the errors, that he described, but there are more problems in your code.

1. Look at these two lines, that I got from your sketch. I already corrected, what Calvin had to say about the if statement.

```
#define trigPin_up 2
if (trigPin_up == HIGH && trigPin_down == LOW){

```

You define `trigPin_up` as the number two. A define is read by the preprocessor. It will replace all occurances of `trigPin_up` with the number 2. `HIGH` and `LOW` are also defines (defined in the Arduino core) with the values 1 and 0. They also get replaced. After that the code goes to the actual compiler. So the compiler sees this if statement:

```
if( 2 == 1 && 4 == 0)

```

2 isn't equal 1 and 4 isn't equal 0, so the result is always false. That corrupts your complete logic. I'm sure you want to read the state of the pin. `trigPin_up` and siblings are only the pin numbers. For getting the real electrical state of the pin you need to actually read it via `digitalRead()`:

```
if(digitalRead(trigPin_up) == HIGH && digitalRead(trigPin_down) == LOW){

```

You can simplify this even more, when you know, that zero is treated as `false` and every other value as `true`:

```
if(digitalRead(trigPin_up) && !digitalRead(trigPin_down)){

```

The `!` before the second `digitalRead()` does a negation, so that the part after the `&&` will become true, if `digitalRead(trigPin_down)` evaluates to false.
2. Now look at these lines:

```
#define NUM_LEDS    13
CRGB leds[NUM_LEDS];
leds[13] = CRGB(0, 0, 0);

```

You create an array named `leds` with `NUM_LEDS` (13) elements. The first index is 0 (as we start to count from zero in most programming languages). But that means, that the last index in the array is 12, not 13. When doing `leds[13]=...` you actually write to a memory address outside of your array. It could be everything, what is saved there. And you overwrite it. This often is a hard to diagnose problem, since it can have very weird consequences. Calvin Bootsman also did this wrong in his answer. For the for loop you only should count to 12, meaning using `i < 13` or `i < NUM_LEDS` in the for loop.
3. Then I guess you don't really understand how the logic of interfacing the HC-SR04 works. The trigger pins, that you define, are outputs. Their state will only change, if you yourself change it via `digitalWrite()`. But that cannot happen, as you enclosed the statements doing it into the if statement. It does not make sense to read these pins either. Instead you should write if statements with the calculated distance. You could go with the following flow in you `loop()` function: Trigger first HC-SR04, read the echo back, trigger second HC-SR04, read the echo back, if statement to compare the calculated distances to a trigger value, in there if statements to decide, which one was triggered, execute the corresponding code in it.

---

Honestly I'm suprised, that your code even compiled. You should look into some basic C/C++ tutorials, so that you get the programming syntax right. Also you should carefully think about the logic of your program. Often it is better to first write down short notes, what the logic of the program should be, without really writing the code. That helps with focussing on the logic instead of the syntax. That can be done afterwards.
> 0 votes

---
Tags: programming, hc-sr04
---


# Question
Title: I can't receive string that I have sent through nrf correctly
I'm using arduino uno and nrf24l01. to monitor sensor data. But this is the message that master receives:

>

this is my slave code.

```
void monitoring() {
    delay(10);
    radio.stopListening();
    int soilMoisture = analogRead(A5);
    int light = analogRead(A4);
    float temp = analogRead(A3);
    temp = temp * 0.48828125;
    int ltemp = int(temp);
    String message = String(soilMoisture) + "," + String(light) + "," +    String(ltemp);
    Serial.println(message);
    delay(200);
    radio.write(&message, sizeof(message));
    delay(50);
    radio.startListening();
    delay(10);
}

```

and here is my master code.

```
while (1) {
    if (radio.available()) {
      char message[32] = "";
      radio.read(&message, sizeof(message));
      delay(500);
      Serial.println(message);
}

```

# Answer
Remove the & in the master code line, change

```
 radio.read(message, sizeof(message));

```

to

```
radio.read(message, sizeof(message));

```

`message` is an array, so either you should pass the address of the first character (`&message[0]`), or simply pass `message`.

Another problem is sending a String in the slave code (using type `String`). It's better not to use this type anyway, but you probably have to convert it to a character array of the same type as in the master code.

You can use the function `StringToCharArray` for that, see StringToCharArray.
> 1 votes

---
Tags: arduino-uno, arduino-ide, string, nrf24l01+, pointer
---


# Question
Title: cant figure out how to fix this compile error
evrything worked for a bit and changed to much to get it working again. dont really understand the error.

\[!\[C:\Users\bavob\AppData\Local\Temp\ccyfrkaL.ltrans0.ltrans.o: In function \`loop':

C:\Users\bavob\Documents\Arduino\counte\_up/counte\_up.ino:96: undefined reference to \`num\_Write(int)'

collect2.exe: error: ld returned 1 exit status

exit status 1 Fout bij het compileren voor board Arduino/Genuino Uno\]\]

```
  { 1, 1, 1, 1, 1, 0, 1 }, // 0
  { 0, 1, 1, 0, 0, 0, 0 }, // 1
  { 1, 1, 0, 1, 1, 1, 0 }, // 2
  { 1, 1, 1, 1, 0, 1, 0 }, // 3
  { 0, 1, 1, 0, 0, 1, 1 }, // 4
  { 1, 0, 1, 1, 0, 1, 1 }, // 5
  { 1, 0, 1, 1, 1, 1, 1 }, // 6
  { 1, 1, 1, 0, 0, 0, 0 }, // 7
  { 1, 1, 1, 1, 1, 1, 1 }, // 8
  { 1, 1, 1, 0, 0, 1, 1 }  // 9
};

int pin = 2;
int buttonState = 0;
const int button = 12;
int led = 13;
int randVal;
bool pressVal;
void num_Write(int);
void setup() {
  pinMode(2, OUTPUT);
  pinMode(3, OUTPUT);
  pinMode(4, OUTPUT);
  pinMode(5, OUTPUT);
  pinMode(6, OUTPUT);
  pinMode(7, OUTPUT);
  pinMode(8, OUTPUT);
  pinMode(led, OUTPUT);
  Serial.begin(9600);
  pinMode(button, INPUT);
}

void loop() {
  buttonState = digitalRead(button);
  if (buttonState == LOW) {
    turnOff();
    pressVal = false;
  }
  else
  {
    if (pressVal == false)
    {
      randVal = rand() % 10;
      pressVal = true;
    }
    Serial.println(randVal);
    if (randVal == 0)
    {
      void zero(int number);
      num_Write(0);
    }
    else if (randVal == 1)
    {
      void one(int number);
      num_Write(1);
    }
    else if (randVal == 2)
    {
      void two(int number);
      num_Write(2);
    }
    else if (randVal == 3)
    {
      void three(int number);
      num_Write(3);
    }
    else if (randVal == 4)
    {
      void four(int number);
      num_Write(4);
    }
    else if (randVal == 5)
    {
      void five(int number);
      num_Write(5);
    }
    else if (randVal == 6)
    {
      void six(int number);
      num_Write(6);
    }
    else if (randVal == 7)
    {
      void seven(int number);
      num_Write(7);
    }
    else if (randVal == 8)
    {
      void eight(int number);
      num_Write(8);
    }
    else
    {
      void nine(int number);
      num_Write(9);
    }
  }
}

void zero(int number)
{
  for (int j = 0; j < 7; j++) {
    digitalWrite(pin, num_array[number][j]);
    pin++;
  }
}

void one(int number)
{
  for (int j = 0; j < 7; j++) {
    digitalWrite(pin, num_array[number][j]);
    pin++;
  }
}

void two(int number)
{
  for (int j = 0; j < 7; j++) {
    digitalWrite(pin, num_array[number][j]);
    pin++;
  }
}
void three(int number)
{
  for (int j = 0; j < 7; j++) {
    digitalWrite(pin, num_array[number][j]);
    pin++;
  }
}
void four(int number)
{
  for (int j = 0; j < 7; j++) {
    digitalWrite(pin, num_array[number][j]);
    pin++;
  }
}
void five(int number)
{
  for (int j = 0; j < 7; j++) {
    digitalWrite(pin, num_array[number][j]);
    pin++;
  }
}
void six(int number)
{
  for (int j = 0; j < 7; j++) {
    digitalWrite(pin, num_array[number][j]);
    pin++;
  }
}
void seven(int number)
{
  for (int j = 0; j < 7; j++) {
    digitalWrite(pin, num_array[number][j]);
    pin++;
  }
}
void eight(int number)
{
  for (int j = 0; j < 7; j++) {
    digitalWrite(pin, num_array[number][j]);
    pin++;
  }
}
void nine(int number)
{
  for (int j = 0; j < 7; j++) {
    digitalWrite(pin, num_array[number][j]);
    pin++;
  }
}
void turnOff()
{

}

```

# Answer
You call function `num_Write` a lot, you create a forward declaration:

void num\_Write(int);

But you forgot to create the implementation.

If you would have forgot the forward declaration the function would not be known at all (and you would get a compiler error). But with the forward declaration you let the compiler know the signature of `num_write` (so the return value and argument types).

When the linker wants to link all object (.o) files together it cannot find an implementation of the function `num_write` and you get this error. Hence `ld` is the linker.
> 2 votes

---
Tags: arduino-uno, programming, linker
---