message:
'D1' was not declared in this scope; did you mean 'y1'?

Even though i am mentioning everything in the beginning then too m getting out of scope error. Code Reference :- https://noisycarlos.com/project/how-to-turn-your-computer-on-and-off-remotely/
I dont know what wwrong here. I am using ESP8266 module. Please help.

    #include <ESP8266WiFi.h>

        const char* ssid = <YOUR WIFI NAME>;
        const char* password = <YOUR WIFI PASSWORD>;
        const char ON = '+',
         OFF = '-',
         SLEEP = '/',
         AUTO = 'A';

        const int pinPowerLightOut = D1,
         pinPowerLightIn = D5,
         pinPowerButton = D6,
         pinResetButton = D7,

         buttonPressTime = 250;

        char currentStatus = OFF;
        char lightStatus = AUTO;

        unsigned long autoDisconnectTime = 0,
         powerButtonReleaseTime = 0;

        WiFiServer wifiServer(80);
        WiFiClient client;

        unsigned long lastOn = 0,
         lastOff = 0;

        void changeStatusTo(char newStatus)
        {
         if(newStatus != currentStatus)
         {
         Serial.print("Status changed to ");
         Serial.println(newStatus);

         }
         currentStatus = newStatus;
        }

        void recordLightStatusChange(bool lightIn)
        {
         if(lightIn)
         lastOn = millis();
         else
         lastOff = millis();

        if(lightStatus == AUTO);
         digitalWrite(pinPowerLightOut, lightIn);

        }
        void statusChange()
        {
         bool currentLightStatus = !digitalRead(pinPowerLightIn);

        if(lastOn != 0 && lastOff != 0)
         {
         if((millis() < lastOn + 4000) && (millis() < lastOff + 4000))
         {
         changeStatusTo(SLEEP);
         recordLightStatusChange(currentLightStatus);
         return;
         }
         }

        if(currentLightStatus)
         changeStatusTo(ON);
         else
         changeStatusTo(OFF);

         recordLightStatusChange(currentLightStatus);
        }

        void Print(String toPrint)
        {
         client.print(toPrint);
         Serial.print(toPrint);
        }
        void Println(String toPrint)
        {
         client.println(toPrint);
         Serial.println(toPrint);
        }

        void processCommand(String command)
        {
         Serial.print(F("Received command "));
         Serial.println(command);

        if(command.equalsIgnoreCase(F("status")))
         {
         Print("Status: ");
         if(currentStatus == ON)
         Println("On");
         else if(currentStatus == OFF)
         Println("Off");
         else if(currentStatus == SLEEP)
         Println("Sleeping");
         }
         else if(command.equalsIgnoreCase(F("on")))
         {
         if(currentStatus != ON)
         {
         Println("Power Button Pressed (powering on)");
         pressPowerButton(buttonPressTime);
         }
         else
         Println("Machine is already on (button not pressed)");

        }
         else if(command.equalsIgnoreCase(F("off")))
         {
         if(currentStatus == ON)
         {
         Println("Power Button Pressed (powering off)");
         pressPowerButton(buttonPressTime);
         }
         else
         Println("Machine is already off (button not pressed)");

        }
         else if(command.equalsIgnoreCase(F("reset")))
         {
         unsigned long releaseTime = millis() + 500;
         digitalWrite(pinResetButton, HIGH);
         while(millis() < releaseTime)
         {}
         digitalWrite(pinResetButton, LOW);

        Println("Reset Button Pressed");
         }
         else if(command.equalsIgnoreCase(F("force off")))
         {
         if(currentStatus != OFF)
         {
         Print("Holding Power Button for 10 seconds...");
         pressPowerButton(10000);
         }
         }
         else if(command.equalsIgnoreCase(F("pressPwr")))
         {
         digitalWrite(pinPowerButton, HIGH);
         Println("Power Button Pressed");
         }
         else if(command.equalsIgnoreCase(F("releasePwr")))
         {
         digitalWrite(pinPowerButton, LOW);
         Println("Power Button Released");
         }
         else if(command.equalsIgnoreCase(F("light on")))
         {
         setLightStatus(ON);
         }
         else if(command.equalsIgnoreCase(F("light off")))
         {
         setLightStatus(OFF);
         }
         else if(command.equalsIgnoreCase(F("light auto")))
         {
         setLightStatus(AUTO);
         }
        }

        void setLightStatus(char newStatus)
        {
         if(newStatus == ON)
         {
         digitalWrite(pinPowerLightOut, HIGH);
         Println("Light On");
         return;
         }

         if(newStatus == OFF)
         {
         digitalWrite(pinPowerLightOut, LOW);
         Println("Light Off");
         return;
         }

         if(newStatus == AUTO)
         {
         Println("Light Set to Auto");
         setLightStatus(currentStatus);
         }

        }

        void pressPowerButton(int duration)
        {
         powerButtonReleaseTime = millis() + (duration);
         digitalWrite(pinPowerButton, HIGH);
        }

        void runRoutineChecks()
        {
         checkIfPowerNeedsToRelease();

        if((millis() > lastOn + 4000) && (millis() > lastOff + 4000))
         statusChange();
        }

        void checkIfPowerNeedsToRelease()
        {
         if(powerButtonReleaseTime != 0)
         {
         if(millis() >= powerButtonReleaseTime)
         {
         digitalWrite(pinPowerButton, LOW);
         powerButtonReleaseTime = 0;
         Println("Power Button Released");
         }
         }
        }

        /////////////----------------------------------------------------------------------------

        void setup() {
         Serial.begin(115200);
         pinMode(pinPowerLightIn, INPUT_PULLUP);
         pinMode(pinPowerLightOut, OUTPUT);
         pinMode(pinPowerButton, OUTPUT);
         pinMode(pinResetButton, OUTPUT);

         attachInterrupt(digitalPinToInterrupt(pinPowerLightIn), statusChange, CHANGE);

         WiFi.begin(ssid, password);

        while (WiFi.status() != WL_CONNECTED)
         {
         delay(1000);
         Serial.println("Connecting..");
         }

        Serial.print("Connected to WiFi. IP:");
         Serial.println(WiFi.localIP());

         wifiServer.begin();
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////////

        void loop()
        {

         runRoutineChecks();

         client = wifiServer.available();
         if (client)
         {
         while (client.connected())
         {
         String comm = "";
         while (client.available()>0)
         {
         char c = client.read();

        autoDisconnectTime = millis() + 60000;

         if(c == ';')
         {
         processCommand(comm);
         comm = "";
         }
         else
         {
         comm.concat(c);
         }
         }
         runRoutineChecks();
         if(autoDisconnectTime > 1000 && millis() > autoDisconnectTime)
         {
         Serial.println("Client timeout");
         client.stop();
         }
         }
         client.stop();
         Serial.println("Client disconnected");
         autoDisconnectTime = 0;
         }
        }

The ERROR :-
~~~
NODEMCU:2:30: error: 'D1' was not declared in this scope; did you mean 'y1'?
    2 | const int pinPowerLightOut = D1,
      |                              ^~
      |                              y1
C:\Users\wahid\Documents\Arduino\NODEMCU\NODEMCU.ino: In function 'void statusChange()':
NODEMCU:61:42: error: 'pinPowerLightIn' was not declared in this scope; did you mean 'pinPowerLightOut'?
   61 |   bool currentLightStatus = !digitalRead(pinPowerLightIn);
      |                                          ^~~~~~~
      |                                          pinPowerLightOut
C:\Users\wahid\Documents\Arduino\NODEMCU\NODEMCU.ino: In function 'void processCommand(String)':
NODEMCU:118:24: error: 'buttonPressTime' was not declared in this scope
  118 |       pressPowerButton(buttonPressTime);
      |                        ^~~~~~~
NODEMCU:130:24: error: 'buttonPressTime' was not declared in this scope
  130 |       pressPowerButton(buttonPressTime);
      |                        ^~~~~~~
NODEMCU:140:18: error: 'pinResetButton' was not declared in this scope
  140 |     digitalWrite(pinResetButton, HIGH);
      |                  ^~~~~~
NODEMCU:158:18: error: 'pinPowerButton' was not declared in this scope; did you mean 'pressPowerButton'?
  158 |     digitalWrite(pinPowerButton, HIGH);
      |                  ^~~~~~
      |                  pressPowerButton
NODEMCU:163:18: error: 'pinPowerButton' was not declared in this scope; did you mean 'pressPowerButton'?
  163 |     digitalWrite(pinPowerButton, LOW);
      |                  ^~~~~~
      |                  pressPowerButton
C:\Users\wahid\Documents\Arduino\NODEMCU\NODEMCU.ino: In function 'void pressPowerButton(int)':
NODEMCU:212:16: error: 'pinPowerButton' was not declared in this scope; did you mean 'pressPowerButton'?
  212 |   digitalWrite(pinPowerButton, HIGH);
      |                ^~~~~~
      |                pressPowerButton
C:\Users\wahid\Documents\Arduino\NODEMCU\NODEMCU.ino: In function 'void checkIfPowerNeedsToRelease()':
NODEMCU:232:20: error: 'pinPowerButton' was not declared in this scope; did you mean 'pressPowerButton'?
  232 |       digitalWrite(pinPowerButton, LOW);
      |                    ^~~~~~
      |                    pressPowerButton
C:\Users\wahid\Documents\Arduino\NODEMCU\NODEMCU.ino: In function 'void setup()':
NODEMCU:246:11: error: 'pinPowerLightIn' was not declared in this scope; did you mean 'pinPowerLightOut'?
  246 |   pinMode(pinPowerLightIn, INPUT_PULLUP);
      |           ^~~~~~~
      |           pinPowerLightOut
NODEMCU:248:11: error: 'pinPowerButton' was not declared in this scope; did you mean 'pressPowerButton'?
  248 |   pinMode(pinPowerButton, OUTPUT);
      |           ^~~~~~
      |           pressPowerButton
NODEMCU:249:11: error: 'pinResetButton' was not declared in this scope
  249 |   pinMode(pinResetButton, OUTPUT);
      |           ^~~~~~
exit status 1
'D1' was not declared in this scope; did you mean 'y1'?
~~~

body:
Only for some esp8266 dev boards Dx pins are defined. The constants map esp module pin numbers to board's pin numbers (for example on most of them D1 is io 4).

**If you have a dev board with Dx labels on the PCB, then select the right board in Tools menu.**

For plain esp8266 module use pin numbers in code. If the author of the code had a Wemos D1 mini or a NodeMci dev board, use [the Dx definitions in the header file][1] to map the Dx pins to esp8266 pins.

Note that on esp8266 not all pins are general purpose IO. Some have limited usage, so use the same esp8266 pins as the author of the code.

  [1]: https://github.com/esp8266/Arduino/blob/9fcf14f81fa9be589530e9596b7c5a264dc81ee8/variants/nodemcu/pins_arduino.h#L40


sender: user

message:
Breathing LEDs on single PWM pin?

I'm doing a project which is essentially a lighted cube, that communicates status through different colors, where I get this ides [it][1] (having code). So when the light goes below a certain level it turns a certain color, when temp goes above a certain level it turns another color, etc. I'm figuring I'll probably need anywhere from 2 to 4 LEDs per color to get a nice intensity, and the colors would breathe, which is pretty easy with PWM on the arduino.

What I'm thinking is that I'm going to leave all the colors in phase. So that the intensity ramp on red is the same as yellow, is the same as green, etc. That would require only a single PWM output and most importantly, a single section in the code, which would make writing easier.

The solution I've come up with is to have the PWM pin drive a MOSFET, and give it the modulation, and the MOSFET would repeat the "breathing" pulse to all the LEDs. Then each color gets switched on or off through a transistor by other pins on the arduino that simply go high or low.

I figure an IRF630, which has an insanely high drain current for this purpose should be more than enough for whatever I might plug into it. And for the switching of each color, maybe an N2222, 4 LEDs will go at about 80 mA max anyway.

So, why not just drive each color from a PWM output? Any thoughts on the circuit? Sound like it could work?

  [1]: https://www.kynix.com/Blog/Arduino-Complete-Guide-for-Beginners-with-Examples.html Code Source

sender: assistant

body:
From your description I think you are wanting this arrangement:

<!-- Begin schematic: In order to preserve an editable schematic, please
     don't edit this section directly.
     Click the "edit" link below the image in the preview instead. -->

![schematic](https://i.stack.imgur.com/JsZcG.png)

<!-- End schematic -->

There is no logical problem with that arrangement. However you must watch the total current being provided by each GPIO pin. You must not go above 40mA peak, and you should not go above 25mA sustained.

It may be better to provide the 5V to the LEDs through a P-channel MOSFET per bank to allow for higher current:

<!-- Begin schematic: In order to preserve an editable schematic, please
     don't edit this section directly.
     Click the "edit" link below the image in the preview instead. -->

![schematic](https://i.stack.imgur.com/volxC.png)

<!-- End schematic -->

Note that here the operation of the GPIO is reversed: the gate of the P-channel MOSFET must be pulled LOW to turn it on.


message:
Stabilize data from four gyros/accelerometer

I am currently working on a university project. My aim is to get a rough estimate of the posture of a person's back. For this I have built a system that collects the data from 4 MPU6050 at a central service. From there it will be visualised. My first idea was to draw 4 lines and take the roll angles for the angles between the lines. My problem is that the data from the MPU6050s drifts a lot. I have already created calibration data and use a complementary filter on the nodeMCUs that read the data from the MPUs.

I am using the Adafruit_MPU6050.h lib to connect to the sensors and get data from it. To calculate roll, pitch and yaw I use the following code:

```cpp
  sensors_event_t gyro_1;
  sensors_event_t accel_1;
  mpu_gyro_1->getEvent(&gyro_1);
  mpu_accel_1->getEvent(&accel_1);

  acc_1_angle_x = (atan(accel_1.acceleration.y / sqrt(pow(accel_1.acceleration.x, 2) + pow(accel_1.acceleration.z, 2))) * 180 / PI) - mpu_1_acc_err_x;
  acc_1_angle_y = (atan(-1 * accel_1.acceleration.x / sqrt(pow(accel_1.acceleration.y, 2) + pow(accel_1.acceleration.z, 2))) * 180 / PI) - mpu_1_acc_err_y;

  previousTime = currentTime;
  currentTime = millis();
  elapsedTime = (currentTime - previousTime) / 1000;

  gyro_1_angle_x = gyro_1_angle_x + (gyro_1.gyro.x - mpu_1_gyro_err_x) * elapsedTime; // deg/s * s = deg
  gyro_1_angle_y = gyro_1_angle_y + (gyro_1.gyro.y - mpu_1_gyro_err_y) * elapsedTime;
  yaw_1 = yaw_1 + (gyro_1.gyro.z - mpu_1_gyro_err_z) * elapsedTime;
  roll_1 = 0.96 * gyro_1_angle_x + 0.04 * acc_1_angle_x;
  pitch_1 = 0.96 * gyro_1_angle_y + 0.04 * acc_1_angle_y;

```

How can I make my data more stable?
I tried playing with the 0.96 and 0.04 to change the amount of data I use from the gyro but it only got worse.

If you are interested, this is my project github:
https://github.com/Trojan13/posture-control

Thanks in advance for your input!

body:
Looking at your code, I see the only place where `gyro_1_angle_x` is
updated is here:

```c++
gyro_1_angle_x = gyro_1_angle_x
    + (gyro_1.gyro.x - mpu_1_gyro_err_x) * elapsedTime;
```

This is adding to `gyro_1_angle_x` a quantity that does not depend on
`gyro_1_angle_x` itself. This means that, if there is an uncorrected
systematic error in the measurement of `gyro_1.gyro.x` (which there
always is, as you can never achieve _perfect_ calibration), the errors
will pile up, leading to an unbounded drift. Then, you estimate the roll
angle as

```c++
roll_1 = 0.96 * gyro_1_angle_x + 0.04 * acc_1_angle_x;
```

The factor 0.96 slightly reduces the amount of drift (by 4%), but does
not change the qualitative behavior: `roll_1` is also prone to unbounded
drift.

## Suggested approach

My suggestion will be to forget about angles. Using angles to keep track
of your device's attitude is a bad idea: the formulas needed to update
the angles are complex (and thus easy to get wrong), computationally
expensive, and prone to [gimbal lock][gimbal]. For tracking the whole
attitude, it would be more reasonable to use rotation matrices or,
better yet, quaternions.

In your use case, however, you do not need to track the whole attitude.
You have no means to reliably track the yaw angle, and you actually do
not even care about this angle. You are only interested in the
orientation of the device relative to the vertical direction. Thus I
suggest you do no even try to track the attitude, and instead just track
the vertical direction. This direction is given by the coordinates of
the gravity vector in the device's reference frame. Then you just have
one vector to track. No angles, no matrices, no quaternions: just a
simple vector.

### Using the accelerometers

The accelerometers are sensitive to the gravity, thus you can use their
readings as an estimate of the gravity vector, as in the following
pseudo-code:

    at each time step:
        (accel, gyro) = read_MPU();
        gravity = accel;

This may give you the opposite of the gravity (direction of the zenith).
That's fine, as long as you know which vector you are tracking.

There is an issue with this approach though. The accelerometers are not
only sensitive to the gravity, they are also sensitive to the
acceleration (hence the name). If your subject moves, its acceleration
will cause an error in the estimate of the gravity vector. The estimate
is poor in the short term, but it should be good in the long term: as
your subject is unlikely to maintain _sustained_ acceleration, a time
average of the accelerometer readings should closely match the gravity
vector.

### Using the gyroscopes

In order to get rid of the acceleration-induced errors, you can instead
use the gyro readings. Assuming you somehow manage to get an initial
estimate of the gravity vector, you can use the gyro readings to
iteratively update this estimate:

    at each time step:
        (accel, gyro) = read_MPU();
        dt = time_since_previous_time_step;
        rotation = - dt * gyro;
        gravity = apply_rotation(rotation, gravity);

here `rotation` is the [rotation vector][rot-vector] describing how much
the gravity has rotated since the previous time step. The minus sign in
its formula comes from the fact that the gyro gives you the rotation of
the device relative to a still reference frame, whereas you want the
rotation of a still vector relative to the device's reference frame. The
function `apply_rotation()` would apply [Rodrigues' rotation
formula][rotation] in order to rotate the gravity vector to its new
orientation.

This approach does not suffer from the acceleration induced errors. It
is, however prone to drift, as combining a large number of small
rotations ends up piling up a large number of small errors.

### Combining gyroscope and accelerometer data

The accelerometer approach is prone to short-term errors, while the
gyroscope approach is prone to long-term drift. You can try to combine
these two approaches, and use the accelerometers to determine the
long-term behavior of your gravity estimate, while the gyroscopes
determine its short-term behavior. For this you would, at each time
step:

* use the gyro data to rotate the current estimate of the gravity vector
* then “stir” it gently towards the accelerometer readings.

In pseudo-code, this would look like:

    at each time step:
        (accel, gyro) = read_MPU();
        dt = time_since_previous_time_step;
        rotation = - dt * gyro;
        gravity = apply_rotation(rotation, gravity);
        gravity = gravity + (dt/tau) * (accel - gravity)

The last line has the effect of slightly pushing the gravity estimate
towards the accelerometer readings. Note that this line looks like the
implementation of a first-order low-pass filter with time constant
`tau`. This time constant defines the boundary between the “short” time
scales, where you trust the gyroscopes more than the accelerometers, and
the “long” time scales, where you trust more the accelerometers. The
value of `tau` has to be chosen by experiment. It controls the trade-off
between the noise coming from the acceleration and the systematic error
coming from the gyros.

With this formula, the accumulated gyro errors will always stay bound,
with a total error proportional to `tau`. Since the step-wise rotations
are presumably very small, and since the rotation errors do not pile up
in an unbounded way, you can probably get away with using a
linearization of the Rodrigues' rotation formula (cos θ = 1, sin θ = θ):

    gravity = gravity + rotation × gravity

and then you need no trigonometry at all.

It is also worth noting that, with this approach, you can safely
initialize `gravity` to zero: it will immediately start growing as the
program runs, and its magnitude will eventually converge to the
appropriate value.

### Getting the pitch and roll

Once you know the gravity vector, you can easily compute the pitch and
roll. I am not saying that you should completely avoid using angles: you
probably want angles on your user interface. What I am saying is that
you should refrain from using angles for the purpose of keeping track of
the device's orientation. Computing the angles as a post-processing step
is fine.

Actually, you may as well compute those angles in the computer that does
the final processing of the data. The ESPs can simply send their best
estimate of the gravity vector, and let the computer do the
trigonometry.

[gimbal]: https://en.wikipedia.org/wiki/Gimbal_lock
[rot-vector]: https://en.wikipedia.org/wiki/Axis–angle_representation#Rotation_vector
[rotation]: https://en.wikipedia.org/wiki/Rodrigues'_rotation_formula


body:
You have the right idea fusing data from both gyro and accelerometer. However, I would strongly advise against doing the fusion yourself since there is a dedicated Digital Motion Processor (DMP) on your MPU-6050 that does this for you. You just need a library that grabs data from the DMP. As far as I know the only Arduino libraries that do this are ones based on Jeff Rowberg's work.

The data outputted by the DMP is in quaternion format. Jeff converts it to yaw pitch and roll but his conversion is flawed (it produces spurious flips and rotations at north and south poles, called gimbal lock). Don't worry, this can be fixed.

If using Jeff's library (or one based on it) you'll need to make sure the detector is level and still before sending a character over serial to trigger the calibration and you need to do this every time you power on. The library and sketches are somewhat overwhelming/intimidating to new users. This too can be fixed.

If you want to

(a) Learn more about this whole topic

(b) Use the correct conversion from quaternion to yaw pitch roll (one that does not produce gimbal lock)

(c) Hide Jeff's library behind a simple and easy to use interface

(d) Perform the calibration only once and have those results saved to persistent memory on your arduino so that you don't have to repeat the calibration every time you power on the device.

Then I would recommend the following tutorial:

https://youtu.be/k5i-vE5rZR0


message:
SparkFun RedBoard PTH Kit wrongly configured hardware

I have a [SparkFun RedBoard PTH Kit][1]. It's not made by SparkFun, but by https://inmotion.pt (that doesn't exist anymore). I soldered it, and bought a FTDI adapter, but when I try to upload the blink example the Arduino IDE I get this error:

    Sketch uses 1030 bytes (3%) of program storage space. Maximum is 32256 bytes.
    Global variables use 9 bytes (0%) of dynamic memory, leaving 2039 bytes for local variables. Maximum is 2048 bytes.
    avrdude: stk500_recv(): programmer is not responding
    avrdude: stk500_getsync() attempt 1 of 10: not in sync: resp=0xa6
    avrdude: stk500_recv(): programmer is not responding
    avrdude: stk500_getsync() attempt 2 of 10: not in sync: resp=0xa6
    avrdude: stk500_recv(): programmer is not responding
    avrdude: stk500_getsync() attempt 3 of 10: not in sync: resp=0xa6
    avrdude: stk500_recv(): programmer is not responding
    avrdude: stk500_getsync() attempt 4 of 10: not in sync: resp=0xa6
    avrdude: stk500_recv(): programmer is not responding
    avrdude: stk500_getsync() attempt 5 of 10: not in sync: resp=0xa6
    avrdude: stk500_recv(): programmer is not responding
    avrdude: stk500_getsync() attempt 6 of 10: not in sync: resp=0xa6
    avrdude: stk500_recv(): programmer is not responding
    avrdude: stk500_getsync() attempt 7 of 10: not in sync: resp=0xa6
    avrdude: stk500_recv(): programmer is not responding
    avrdude: stk500_getsync() attempt 8 of 10: not in sync: resp=0xa6
    avrdude: stk500_recv(): programmer is not responding
    avrdude: stk500_getsync() attempt 9 of 10: not in sync: resp=0xa6
    avrdude: stk500_recv(): programmer is not responding
    avrdude: stk500_getsync() attempt 10 of 10: not in sync: resp=0xa6
    Problem uploading to board.  See https://support.arduino.cc/hc/en-us/sections/360003198300 for suggestions.

Or if I try to reset while uploading:

    avrdude: stk500_recv(): programmer is not responding
    avrdude: stk500_getsync() attempt 1 of 10: not in sync: resp=0x63
    avrdude: stk500_getsync() attempt 2 of 10: not in sync: resp=0xff
    avrdude: stk500_getsync() attempt 3 of 10: not in sync: resp=0xfe
    avrdude: stk500_getsync() attempt 4 of 10: not in sync: resp=0xff
    avrdude: stk500_getsync() attempt 5 of 10: not in sync: resp=0xfe
    avrdude: stk500_getsync() attempt 6 of 10: not in sync: resp=0xff
    avrdude: stk500_getsync() attempt 7 of 10: not in sync: resp=0xff
    avrdude: stk500_getsync() attempt 8 of 10: not in sync: resp=0xfe
    avrdude: stk500_getsync() attempt 9 of 10: not in sync: resp=0xfe
    avrdude: stk500_getsync() attempt 10 of 10: not in sync: resp=0xff
    Problem uploading to board.  See https://support.arduino.cc/hc/en-us/sections/360003198300 for suggestions.

And the link here at the end suggests the problem is wrongly configured hardware: https://support.arduino.cc/hc/en-us/articles/4401874331410--Error-avrdude-when-uploading

So think the problem is that when I connect the ports from the Arduino to the FTDI, two ports don't match:

<!-- Begin schematic: In order to preserve an editable schematic, please
     don't edit this section directly.
     Click the "edit" link below the image in the preview instead. -->

![Schematic](https://i.stack.imgur.com/L7T1M.png)

<!-- End schematic -->

---

Here's a picture of the soldering, though I don't think that is the problem: https://i.stack.imgur.com/aa2j5.jpg

---

I am using these drivers: https://github.com/MCUdude/MiniCore for the Arduino. With these settings:

[![Driver settings][2]][2]

The options only have these variants:
- 328P / 328PA
- 328 / 328A
- 328PB

But my processor says 328P-PU. I tried every one of them and they all give me the same error above.

---

Can I even use this FTDI adapter? If yes what would the setup be?

  [1]: https://www.sparkfun.com/products/retired/10908
  [2]: https://i.stack.imgur.com/6HJWw.png

body:
I got it to work!

The problem was that I had connected the Arduino to the FTDI and not both the FTDI and the Power Brick. The [SparkFun product page][1] said that you can use like that, and the version from https://inmotion.pt that I have is identical so I though it should have worked.

Thank's a lot @jurah for you help!

  [1]: https://www.sparkfun.com/products/retired/10908


message:
Problems connecting to WiFi101 access point

I currently have two Arduino Zero boards (using the SAMD21 microcontroller), each with an ATWINC1500 wifi module attached. I have established one of these units as a wifi access point with a server running on it, while the other unit is a client that attempts to connect to the access point and then send some data to the server.

As far as I can tell, the access point and the server on the first unit are created correctly. I am able to use telnet on a separate Android device to connect to the access point and send data to the server. Unfortunately, when I attempt to connect to the AP/server using the other Arduino board, it is never successful.

**Here is the code I am using on the first board to create the access point and server:**
```
WiFiServer server(23);
WiFiClient client;

void LaunchAccessPoint ()
{
    uint8_t begin_ap_status = WiFi.beginAP(access_point_name);
    if (begin_ap_status == WL_AP_LISTENING)
    {
        server.begin();
    }
}

void HandleClientConnection ()
{
    String result;
    client = server.available();
    if (client && client.connected() && client.available())
    {
        while (client.available())
        {
            result += (char) client.read();
        }

        client.stop();
    }

    SerialUSB.println(result);
}

void setup()
{
    /* ... some code in this function has been cut for clarity ... */
    LaunchAccessPoint();
}

void loop()
{
    /* ... some code in this function has been cut for clarity ... */
    HandleClientConnection();
}
```

**Meanwhile, here is the code for the client that attempts to connect to the AP/server:**
```
bool ConnectToWifi ()
{
    uint8_t wifi_connection_result = 0;
    wifi_connection_result = WiFi.begin(wifi_ssid);
    return (wifi_connection_result == WL_CONNECTED)
}

void PublishData (const char *json_string)
{
    WiFiClient client = WiFiClient();
    int client_connect_success = client.connect(IPAddress(192, 168, 1, 1), 23);
    if (client_connect_success)
    {
        int client_bytes_written = client.println(json_string);
        client.stop();
    }
}

void setup ()
{
    /* some code cut for clarity */
    ConnectToWifi();
}

void loop()
{
    /* some code cut for clarity */
    PublishData(some_string);
}
```

As I said before, *if I try using telnet on a computer or phone, it is able to successfully connect to the server and send data*. But when I attempt to use my Arduino board to act as the client, the socket gets closed by the server, as if it's actively refusing the connection.

EDIT: On the server side, the line `client = server.available();` never returns a client object if server ATWINC is AP and client is the other ATWINC.

Any suggestions? Is there something I am missing or doing wrong? Thanks!

[edit]

After doing some testing, it seems as though the server works *if it is not also acting as an access point*. This is unfortunate, because I need it to act as the access point *and* a server.

If anyone has experience getting two ATWINC1500s to talk to each other, where one is both an AP and a server, and the other is a client, any help would be appreciated!

[/edit]

body:
The bug seems to be that the server must be started *after* the wifi has moved into the WL_AP_CONNECTED state. I am not sure **why** this is, but apparently sockets are invalid (or become invalidated) when the wifi access point is not in this state (or moved out of this state).

So basically, I wrote a couple small functions to handle the state of the server, and then incorporated them in my main loop like so:
```
bool is_server_launched = false;

void LaunchServer_IfDeviceConnected ()
{
    if (!is_server_launched)
    {
        uint8_t wifi_status = WiFi.status();
        if (wifi_status == WL_AP_CONNECTED)
        {
            server.begin();
            is_server_launched = true;
        }
    }
}

void StopServer_IfDeviceDisconnected ()
{
    if (is_server_launched)
    {
        uint8_t wifi_status = WiFi.status();
        if (wifi_status != WL_AP_CONNECTED)
        {
            is_server_launched = false;
        }
    }
}

void loop()
{
    LaunchServer_IfDeviceConnected();
    StopServer_IfDeviceDisconnected();
    HandleClientConnection();
}
```

I know I could have written those functions differently to be in one single function, but I'll do that at another time.

The core of this answer comes from reading the following discussion on the Arduino forums: https://forum.arduino.cc/t/mkr1000-server-in-ap-mode-socket-connection-problem/465719

In that thread, the OP had a similar issue as me. One of the people responding gave the following reply:

> Once the AP connection is lost, the server socket is no longer valid.

That person then suggested adding the following code to the OP's sketch:

```
if (status == WL_AP_CONNECTED) {
  Serial.println("Device connected to AP");
  server.begin(); // <- NEW LINE
} else {
```

After implementing that idea in my code (as I displayed above), it began to work properly.

EDIT: After doing some more digging, I also found this related issue posted in the WiFi101 Github repository:

https://github.com/arduino-libraries/WiFi101/issues/46


message:
Mega 2560 with Adafruit Music Maker and TFT - Pin reroute

I'm building a custom headunit for my motorcycle using the Arduino platform. I wanted to try it as the modular nature of the board and shields looked very versatile. While there does seem to be plenty of documentation on how to use a single shield on a board, there seems to be very scant documentation on how to use multiple shields on a single board.

I tested the Adafruit Music Maker and the TFT separately. My code for each works as expected. However, when I stack them, I run into the issue of how to call each shield to perform it's task.

The issue is the shield pinouts. The MM uses the ICSP to communicate with the board so all I need are:

 - MCS pin - set to pin D7
 - DCS pin - set to pin D6
 - CCS pin - set to pin D4
 - DREQ pin - set to pin D3 (also a Mega interrupt pin)

By itself, the MM shield works correctly using these pins, but in order for the TFT to work, the TFT needs pins D2 to D9 to send LCD data. That means I need to reroute D3,4,6, & 7 for the MM so the signals to the TFT are not interfering on those pins.

I noticed those pins have corresponding hole-throughs on the board.

[![Adafruit MM][1]][1]

Can I use these hole-throughs to redirect the pins to other digital pins on the Mega?

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

body:
Yes, you can. However you will need to isolate them from the existing pins.

If you flip the shield over you should see a set of bridged solder jumpers:

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

You will need to take a small, sharp, craft knife (or something similar) and cut the little track that joins the pads together. If the time ever comes that you want to "undo" that cutting you can just bridge the pads with solder.

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


message:
How to install Adafruit motorshield library in arduino-cli

I need to install [this library](https://github.com/adafruit/Adafruit_Motor_Shield_V2_Library) using the [arduino-cli](https://www.arduino.cc/pro/cli) software. I don't know what name to use for the library. Using
```
arduino-cli lib install <library_name>
```
I have tried `Adafruit_MotorShield`, `Adafruit_MotorShield_V2`, and other random combinations and in all cases it cannot found it. In the library manager of the graphical interface it is this one:

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

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

body:
As pointed out by Juraj♦ in the comments, the name to use can be found in the [`library.properties`](https://github.com/adafruit/Adafruit_Motor_Shield_V2_Library/blob/master/library.properties) file. There we find `name=Adafruit Motor Shield V2 Library` so the command to install the library is:
```
arduino-cli lib install Adafruit\ Motor\ Shield\ V2\ Library
```
Note the white spaces are escaped.


message:
Power to triac dimmer and arduino uno

I am building 2 channel triac dimmer to control led strip lights in my pantry.  Have 4 channel Krida module (just use two, I guess) and Uno.  Have had some success with the triacDimmer library examples, but now realize I'm not sure of my basic approach.

I want to have two light circuits ramp up to a preset light level, then stay on until the power cuts out.  My question is this:  is it possible to power the Arduino Uno and the AC going into the triac module from the same switch?    Will the microcontroller just "start over" every time the power comes on to it - and will the triac be in "off" status without power to its gate?

This is a matter of design, and I'm way out of my depths.  I want to power this project, and write the sketch, so that the two circuits fade on to a  pre-set level when the power comes on.  Is it ok to plan to turn off the lights by just 'pulling the plug?'

Please let me know if this is still not an appropriate question for this forum.  I appreciate any help or feedback.  Thanks

body:
You ask: "is it possible to power the Arduino Uno and the AC going into the triac module from the same switch? Will the microcontroller just "start over" every time the power comes on to it - and will the triac be in "off" status without power to its gate?"
Yes you can put a switch in the line that powers the primary side that feeds both the lights and the UNO power supply. The 4 channel Krida module I have does not turn on the lights until I power the optocoupler. I also have one that has a processor on board and it behaves the same way. When you write your code get a 24V transformer and two 24V lamps to debug your project, that way you will not fry yourself. This is how I normally prototype 120 and 240 Volt circuits. I then test it with the mains when it is all assembled and the test equipment disconnected. Remember some best equipment especially bench type has a connection to the earth ground.


message:
Library that pulls ID3v2 info from MP3s

I'm using an Adafruit Music Maker with a TFT screen on my Mega 2560. I can pull ID3v1 data from the end of an MP3, but I'd like to get the ID3v2 data as I can then push the album cover art to the TFT along with the title/artist/album/etc.

My initial searches have turned up nothing for a library that pulls the ID3v2 headers. Before I start to crack that nut on my own, I want to make sure I am not overlooking something.

Has anyone used a library to pull ID3v2 data from an MP3?

body:
Here's what I have written so far. This pulls data from the ID3v2 header at the start of the mp3 file.

    void frameInfo(File track, char tvalue[64], char albval[64], char artval[64],
    char fname[30], bool showpic) {
    uint32_t start = 10;
    uint32_t lastfrm = 10;
    bool done = false;

    track.getName(fname,max_chars);

    while (!done) {
     uint8_t buff[4];
     uint32_t ltwo[4];
     char tag[5];
     uint32_t fsize;
     track.seek(start);
     track.read((uint8_t *)tag, 4);
     tag[5] = 0;

     track.seek(start + 4);
     track.read((uint8_t *)buff,4);
     ltwo[0] = buff[0];
     ltwo[1] = buff[1];
     ltwo[2] = buff[2];
     ltwo[3] = buff[3];

     fsize = (ltwo[0] << 24) | (ltwo[1] << 16) | (ltwo[2] << 8) | ltwo[3];
     start = start + 10;

    if (tag[0] == 'T' && tag[1] == 'I' && tag[2] == 'T' && tag[3] == '2') {
      uint32_t i;
      int vlen = 0;
      char val[fsize];

      track.seek(start);
      track.read((uint8_t *)val, fsize);
      for (i=0;i<fsize;i++) {
        if (isAlphaNumeric(val[i])) {
          tvalue[vlen] = val[i];
          vlen++;
        }
        else if (val[i] == '(' || val[i] == ')' || val[i] == ' ') {
          tvalue[vlen] = val[i];
          vlen++;
        }
      }
      tvalue[vlen] = '\0';
    }
    else if (tag[0] == 'T' && tag[1] == 'A' && tag[2] == 'L' && tag[3] == 'B') {
      uint32_t i;
      int vlen = 0;
      char val[fsize];

      track.seek(start);
      track.read((uint8_t *)val, fsize);
      for (i=0;i<fsize;i++) {
        if (isAlphaNumeric(val[i])) {
          albval[vlen] = val[i];
          vlen++;
        }
        else if (val[i] == '(' || val[i] == ')' || val[i] == ' ') {
          albval[vlen] = val[i];
          vlen++;
        }
      }
      albval[vlen] = '\0';
    }
    else if (tag[0] == 'T' && tag[1] == 'P' && tag[2] == 'E' && tag[3] == '1') {
      uint32_t i;
      int vlen = 0;
      char val[fsize];

      track.seek(start);
      track.read((uint8_t *)val, fsize);
      for (i=0;i<fsize;i++) {
        if (isAlphaNumeric(val[i])) {
          artval[vlen] = val[i];
          vlen++;
        }
        else if (val[i] == '(' || val[i] == ')' || val[i] == ' ') {
          artval[vlen] = val[i];
          vlen++;
        }
      }
      artval[vlen] = '\0';
    }

    else if (tag[0] == 'A' && tag[1] == 'P' && tag[2] == 'I' && tag[3] == 'C') {
      uint32_t i;
      int vlen = 0;
      char val[30];
      char test[30];
      uint8_t raw[fsize - 11];

      track.seek(start);
      track.read((uint8_t *)val, 11);
      for (i=0;i<11;i++) {
        if (isAlphaNumeric(val[i])) {
          test[vlen] = val[i];
          vlen++;
        }
        else if (val[i] == '(' || val[i] == ')' || val[i] == ' ') {
          test[vlen] = val[i];
          vlen++;
        }
      }
      test[vlen] = '\0';

      if (fsize < 200000) {
        track.seek(start+11);
        Serial.println(fsize+11);
        //track.read((uint8_t *)pic, fsize-11);
      }

    }
    else {

    }

    start = start + fsize;
    if ((start == lastfrm + 10) || start > musicPlayer.mp3_ID3Jumper(track)) {
      done = true;
    }
    else {
      lastfrm = start;
    }

    }
    track.rewind();
    }

This pulls the text data for title/artist/album, but the problem is how to read the image from the header without overloading the Mega. Most of the images are around 30K bytes, but there is no room in RAM on the Mega for that kind of space. I have my sketch set to read the jpeg format, convert it to BMP, then write it to the TFT. Is there some method I could use to have the sketch write the bytes to a file on the SD card, then read them from there?


message:
Whats common practice when using more components than there are pins?

I have a project where I want to use several motors (servo and stepper) which are activated with an RFID and show info on a display.

What’s common practice or a smart way to get past such limitations?

body:
Basically there are 4 ways to go if you run out of pins:

- Change to a microcontroller board with more pins
- Arrange the parts in a smart way to save pins (like if you have many buttons or LEDs you could arrange them as a matrix)
- Use extra peripherals like shift registers, port expanders, PWM chips, ... which need less pins to be controlled
- Use extra microcontrollers to offload some function to them and just communicate over a data bus of your choice (like I2C or Serial) with less pins.

Which of the above is best for you depends on your project and your requirements. Here are some notes about the options:

- Choosing a bigger microcontroller is often the easiest solution, though you need to invest in buying it and rewrite and/or rewire your project. If you change to a different kind of microcontroller it might also involve searching for alternative libraries (since often libraries are not compatible across microcontroller types)
- Arranging buttons or LEDs in a matrix will save you pins, but you also create extra complexity for the software driving them since they need to be actively scanned through all the time. That will take new considerations regarding your program flow (keeping the program responsive using `millis()` and a non-blocking coding style like in the `BlinkWithoutDelay` example)
- With shift registers you need to buy the actual shift registers and with that commit to a data direction (since shift registers come as shift-in and shift-out registers) (as @Mat stated in the comments there are shift registers which support both ways, but they are more complex to use than the standard ones). If you drive something with them you also need to make sure to stay without the specific limitations of that shift register. You need 3 pins for them, but you can daisy chain them. So to drive 4 shift registers you just chain them and still use the 3 pins on your microcontroller. The Arduino Framework provides the `shiftIn()` and `shiftOut()` functions to control them.
- Port expanders usually come with either I2C or SPI interface and are more flexible than shift registers (like different data directions for the pins), but also cost a bit more and are a bit more difficult to control. The Arduino Framework doesn't have direct functions to control them. You can either use the `Wire` or `SPI` library directly (after reading and understanding the communication protocol in the datasheet of the port expander) or you might find a fitting third party library for your specific port expander.
- For driving extra motors or servos a PWM chip can be helpful. These are usually connected via I2C or SPI and can create PWM/servo signals on their outputs. For example the [16 Channel PWM Driver from Adafruit][1]. There are lots of similar products out there, this is just the one, that comes to my mind.
- Using an extra microcontroller might sound a bit wasteful. But it can make things easier, especially if you have multiple things to control which overload the computation capabilities of your microcontroller (with an Uno you can easily get in that terrain). If you pursue this hobby for a while you will often have some microcontrollers lying around. You can get Arduino Nano clones from China for about 1€ per piece. Other microcontrollers are also not expensive. The advantage over the other methods is that you can offload a part of the code to the other microcontroller. While for peripherals like port expanders the logic still happens on your main controller, here you could write more complex logic into the second microcontroller. I used this one time for creating a user interface on a TFT display so that the main microcontroller was free to do its actual job. An additional advantage with extra microcontrollers is (like @Majenko wrote in the comments), that your code gets more modular. For example lets imagine you write code for the extra microcontroller to control the speed of a fan. Then you decide to add more fans to the project. With the modular design you can just add more fans and always take the same code. Or you might wanna add a fan to another project. Just take the existing code and integrate the interface to the second microcontroller in that project.

I hope this helps as an orientation. More definitive answers can only be given here, when you describe your exact situation.

  [1]: https://www.adafruit.com/product/815


body:
There are several ways, but I recommend these:

1. MUXs/DEMUXs for I/O pins
2. Extra peripherals for special function like SPI, USART, ADC, and so on.

1: MUX and DEMUX can make you use more pins with little pins.
For example, you can control extra 2^n pins with n pins. The advantage of MUX and DEMUX is that it respond immediately. However you have to use more pins if you want to control lots of pins and it can only control one pin at a time.

2: You can use additional peripherals to use specific functions like PWM, SPI, ADC and so on. The advantage of this method is that you can use more functions and, in some cases, you control lots of peripherals with less pins. Because of these good features, the peripheral devices are relatively expensive.


message:
RF Keyfob single button code

I'm making a project where a 2 channel RF keyfob (433Mhz) controls an led using arduino nano. As for the hardware everything works and I have tested it with the example decoder code and it works fine. Library I'm using is the RCSwitch.h for receiving.

I have modified the library example code a bit to suit my project. What I'm basically trying to achieve is make an led turn on when I press button A on the keyfob and after a while if I press button A again then the led must turn off. However with my current code, what happens is pressing button A makes the led turn on and pressing button A again does nothing, but if I press button B then the led turns off. So where did I go wrong?

Here is my code
```
#include <RCSwitch.h>

RCSwitch mySwitch = RCSwitch();
int LED = LED_BUILTIN;
boolean statusled = LOW;

void setup() {
  pinMode(LED_BUILTIN, OUTPUT);
  Serial.begin(9600);
  mySwitch.enableReceive(0);  // Receiver on interrupt 0 => that is pin #2
}

void loop() {
  if (mySwitch.available())
  {
    Serial.print(mySwitch.getReceivedValue());
    unsigned long int num = mySwitch.getReceivedValue();
    Serial.print(num);

    if (num == 16130609){
    mySwitch.disableReceive();

      if (statusled == LOW)
      statusled = HIGH;
    }
    else
    {
      statusled = LOW;
    }

    digitalWrite(LED, statusled);
    unsigned long time_now = millis();
    int ck = 500;
    while(millis() <time_now + ck)
    {;}

    mySwitch.resetAvailable();
    mySwitch.enableReceive(0);
  }
}
```

16130609 is the value I get from decoding button A

16130610 is the value from button B

body:
Look again at your logic here:

    if (num == 16130609){
        mySwitch.disableReceive();

        if (statusled == LOW) statusled = HIGH;
    }
    else
    {
        statusled = LOW;
    }

When you press A you will get `num` with the value `16130609`. In the if you turn the LED on, if it is off currently. But you never turn it off there. You will always get in this if statement when pressing A. You don't turn the LED off there, so it doesn't turn off when you press A. When you press B you get another value for `num`. Thus the else clause will get executed, turning the LED off.

So the code is doing exactly, what you told it to do.

**Solution:** Since you want to toggle the LED on press of A, you should just toggle the value of `statusled` in there, instead of explicitly setting it. That would look like this:

    if (num == 16130609){
        mySwitch.disableReceive();

        statusled = !statusled;
    }

I removed the else clause, since you don't want button B to do anything.


message:
Arduino esp32 randomly corrupted variable

Every so often my variable gets corrupted. Sometimes it happens several times in a row and other times it doesn't happen in several hits.
I put these logs to rule out that any of the operations interfered. But as you can see just between one log and another, the data is dirty.

This runs on an ESP32 with arduino as framework and this procedure comes from a freeRTOS dequeue.

**log:**
```
[D][RC_msgRouterProcessCommand.cpp:60] _cloudRXServiceWorker(): Mensaje desencolado:
 topic: iot/riego/prueba/valvula/1
 payload: {
  "controlRemoto": true,
  "modulo": 11,
  "slot": 1,
  "status": 1
}
[D][RC_msgRouterProcessCommand.cpp:61] _cloudRXServiceWorker(): running on core >>>> 0
[D][RC_msgRouterProcessCommand.cpp:62] _cloudRXServiceWorker(): 1 >>>>>>>>>>>>>>>>>>>>>> {
  "controlRemoto": true,
  "modulo": 11,
  "slot": 1,
  "status": 1
}
[D][RC_msgRouterProcessCommand.cpp:63] _cloudRXServiceWorker(): 1-1 >>>>>>>>>>>>>>>>>>>>>> {
  "controlRemoto": true,
  "modulo": 11,
  "slot": 1,
  "status": 1
}
[D][RC_msgRouterProcessCommand.cpp:64] _cloudRXServiceWorker(): 1-2 >>>>>>>>>>>>>>>>>>>>>> {
  "controlRemoto": true,
  "modulo": 11,
  "slot": 1,
  "status": 1
}
[D][RC_msgRouterProcessCommand.cpp:65] _cloudRXServiceWorker(): 1-3 >>>>>>>>>>>>>>>>>>>>>> ��@)�?
[D][RC_msgRouterProcessCommand.cpp:66] _cloudRXServiceWorker(): 1-4 >>>>>>>>>>>>>>>>>>>>>> ��@)�?
[D][RC_msgRouterProcessCommand.cpp:67] _cloudRXServiceWorker(): 1-5 >>>>>>>>>>>>>>>>>>>>>> ��@)�?
[D][RC_msgRouterProcessCommand.cpp:69] _cloudRXServiceWorker(): 2 >>>>>>>>>>>>>>>>>>>>>> ��@)�?
[D][RC_msgRouterProcessCommand.cpp:71] _cloudRXServiceWorker(): 3 >>>>>>>>>>>>>>>>>>>>>> ��@)�?
[D][RC_msgRouterProcessCommand.cpp:72] _cloudRXServiceWorker(): Item count: 5
[D][RC_msgRouterProcessCommand.cpp:73] _cloudRXServiceWorker(): 4 >>>>>>>>>>>>>>>>>>>>>> �^�?
[D][RC_msgRouterProcessCommand.cpp:76] _cloudRXServiceWorker(): Item @ index 0 : iot
[D][RC_msgRouterProcessCommand.cpp:76] _cloudRXServiceWorker(): Item @ index 1 : riego
[D][RC_msgRouterProcessCommand.cpp:76] _cloudRXServiceWorker(): Item @ index 2 : prueba
[D][RC_msgRouterProcessCommand.cpp:76] _cloudRXServiceWorker(): Item @ index 3 : valvula
[D][RC_msgRouterProcessCommand.cpp:76] _cloudRXServiceWorker(): Item @ index 4 : 1
[D][RC_msgRouterProcessCommand.cpp:78] _cloudRXServiceWorker(): 5 >>>>>>>>>>>>>>>>>>>>>> �^�?
[D][RC_msgRouterProcessCommand.cpp:93] _cloudRXServiceWorker(): CASE: RC_HW_TYPE_VALVULA
[D][RC_msgRouterProcessCommand.cpp:94] _cloudRXServiceWorker(): XXXXXXXXXXXXXXXXXXXXXXXXXXX �^�?
[E][RC_msgRouterProcessCommand.cpp:223] _get_valve_typeByPaylod(): _get_valve_typeByPaylod. deserializeJson Json:
 �^�?
[E][RC_msgRouterProcessCommand.cpp:228] _get_valve_typeByPaylod(): Fallo la deserializacion del json
[E][RC_msgRouterProcessCommand.cpp:229] _get_valve_typeByPaylod(): Error: InvalidInput
```

**code fragment:**
```
void RC_msgRouter::_cloudRXServiceWorker(){
    log_d("iniciando worker cloudRXService running on core >>>> %d",xPortGetCoreID());
    msg_t mensaje;
    while (true)
    {
        if(xQueueReceive(QfromCloud, &mensaje , queueSpeed / portTICK_PERIOD_MS)){
            log_d("Mensaje desencolado:\n topic: %s\n payload: %s", mensaje.topic,mensaje.payload);
            log_d("running on core >>>> %d",xPortGetCoreID());
            log_d("1 >>>>>>>>>>>>>>>>>>>>>> %s",mensaje.payload);
            log_d("1-1 >>>>>>>>>>>>>>>>>>>>>> %s",mensaje.payload);
            log_d("1-2 >>>>>>>>>>>>>>>>>>>>>> %s",mensaje.payload);
            log_d("1-3 >>>>>>>>>>>>>>>>>>>>>> %s",mensaje.payload);
            log_d("1-4 >>>>>>>>>>>>>>>>>>>>>> %s",mensaje.payload);
            log_d("1-5 >>>>>>>>>>>>>>>>>>>>>> %s",mensaje.payload);
            StringSplitter *splitter = new StringSplitter(mensaje.topic, '/', -1);  // new StringSplitter(string_to_split, delimiter, limit)
            log_d("2 >>>>>>>>>>>>>>>>>>>>>> %s",mensaje.payload);
            int itemCount = splitter->getItemCount();
            log_d("3 >>>>>>>>>>>>>>>>>>>>>> %s",mensaje.payload);
            log_d("Item count: %d", itemCount);
            log_d("4 >>>>>>>>>>>>>>>>>>>>>> %s",mensaje.payload);
            for(int i = 0; i < itemCount; i++){
                String item = splitter->getItemAtIndex(i);
                log_d("Item @ index %d : %s", i,item);
            }
            log_d("5 >>>>>>>>>>>>>>>>>>>>>> %s",mensaje.payload);
```

body:
The problem was that a task with higher priority interrupts the process. I increased the priority to this task and the problem is solved.

```
xTaskCreatePinnedToCore(_cloudRXServiceTask, "_cloudRXServiceTask", 2048, this, 20, &_cloudRXServiceWorker_handle,0);
```


message:
Read & Write to EEPROM

I need to implement EEPROM Read & Write functionality to my project.

I've been learning how to use the EEPROM on the last few days, however I'm struggling to Read & Write Strings to EEPROM.

**Debugging the Received Data:**
- Received Data: The data received is correct.
- EEPROM Data: It seem it has data but I am receiving Garbage Characters.

After reading several answers, I seem to fail understanding the reason behind my failure.

Sure I could "Copy / Paste", probably make it work and not understand the cloned code, but I wouldn't learn anything from that.

Therefore posting another thread regarding this subject (not exactly duplicate) requesting some help and/or guidance; for the sake of understanding and solving my issue.

**Code**

    int ADDR_USERNAME       = 2;           // Username Data Lenght Address on EEPROM.

    /* Get Username from EEPROM */
    String EE_ReadUsername()
    {
      int dataLength  = EEPROM.read(ADDR_USERNAME);       // Get the Data Length from EEPROM Address Position.
      int dataAddress = ADDR_USERNAME + 1;                // Data Initial Address on EEPROM

      char data[dataLength];                              // Assign the Array Length

      for (int i = 0; i < dataLength; i++)                // Retrieve Data (Char by Char) by Iterating over EEPROM Address Positions.
      {
        char c = EEPROM.read(dataAddress + i);            // Add EEPROM Address Char to Array
      }

      // DEBUG START
      Serial.print("VALUE: ");
      Serial.println(String(data));
      // DEBUG END

      return String(data);                                // Return the Data.
    }

    /* Save Username to EEPROM */
    void EE_WriteUsername(String str)
    {
      byte len = str.length();                            // Get the String Length.
      int dataAddress = ADDR_USERNAME + 1;                // Set the Initial Data Address

      EEPROM.update(ADDR_USERNAME, len);                  // Store the String Length to EEPROM

      for (int i = 0; i < len; i++)                       // Iterate over each char in String.
      {
        EEPROM.update(dataAddress + i, str[i]);           // Assign each char from Received String to an Address Position in EEPROM.
      }
    }

Thanks in advance.

body:
In `EE_ReadUsername()`, you wrote:

```c++
char c = EEPROM.read(dataAddress + i);
```

This variable (`c`) is set but never used. You may want to add that
character to the `data` character array.

Also, the array has to be terminated with a NUL byte.


body:
Giving this thread some more value while taking into consideration @Edgar Bonet's help (the accepted answer for this thread); I'm answering my own question with my full header class code (more EEPROM features) for further reference for myself and other users, who might be learning.

**Note(s):**
1. The regions are there for a backup reference purpose.
2. Feel free to edit and improve the answer and improve comments with advanced and knowleadgeable information.
3. Null Terminating char is NOT added to the EEPROM.
   The Null Terminating char '\n' or '\0' is added to the array when reading (only).
   This prevents writing (unnecessary) addresses to EEPROM.

**Code**

    #pragma region <Includes>
    #include <EEPROM.h>
    #pragma endregion

    #pragma region <Configuration>

    #define ADDR_BRIGHTNESS   0           // LCD Brightness Data Address on EEPROM.
    #define ADDR_CONTRAST     1           // LCD Contrast Data Address on EEPROM. [NOT IMPLEMENTED]
    #define ADDR_USERNAME     2           // Username Data Lenght Address on EEPROM.
    #define ADDR_COMPUTERNAME 14          // Computer Data Length Initial Address on EEPROM.

    #pragma endregion

    #pragma region <CRC>
    unsigned long EEPROM_CRC(void)
    {
      const unsigned long crc_table[16] =
      {
        0x00000000, 0x1db71064, 0x3b6e20c8, 0x26d930ac,
        0x76dc4190, 0x6b6b51f4, 0x4db26158, 0x5005713c,
        0xedb88320, 0xf00f9344, 0xd6d6a3e8, 0xcb61b38c,
        0x9b64c2b0, 0x86d3d2d4, 0xa00ae278, 0xbdbdf21c
      };

      unsigned long crc = ~0L;

      for (int index = 0 ; index < EEPROM.length()  ; ++index)
      {
        crc = crc_table[(crc ^ EEPROM[index]) & 0x0f] ^ (crc >> 4);
        crc = crc_table[(crc ^ (EEPROM[index] >> 4)) & 0x0f] ^ (crc >> 4);
        crc = ~crc;
      }

      return crc;
    }

    /* Performs a Cyclic Redundancy Check and Prints a Report on Serial Monitor */
    void EE_CRC()
    {
      Serial.println(" *** Performing EEPROM Cyclic Redundancy Check...");
      Serial.print(" *** EEPROM Length: ");                                // Print Length of Data to run CRC on.
      Serial.println(EEPROM.length());

      Serial.print(" *** EEPROM CRC32 Data: 0x");                          // Print the Result of Calling EEPROM_CRC()
      Serial.println(EEPROM_CRC(), HEX);
    }
    #pragma endregion

    /* Iterate Through Each byte of the EEPROM Storage and Set all of the bytes to 0. */
    void EE_ERASE()
    {
      Serial.println(" *** ERASING EEPROM MEMORY...");

      for (int i = 0; i < EEPROM.length(); i++)
      { EEPROM.write(i, 0); }

      Serial.println(" *** EEPROM ERASED!");
    }

    #pragma region <User Name>
    /* Get Username from EEPROM */
    String EE_ReadUsername()
    {
      int dataLength  = EEPROM.read(ADDR_USERNAME);         // Get the Data Length from EEPROM Address Position.
      int dataAddress = ADDR_USERNAME + 1;                  // Data Initial Address on EEPROM

      char data[dataLength +1];                             // Assign the Array Length (+1 to Add the Null Terminating Char).

      for (int i = 0; i < dataLength; i++)                  // Retrieve Data (Char by Char) by Iterating over EEPROM Address Positions.
      {
        data[i] = EEPROM.read(dataAddress + i);             // Add EEPROM Address Char to Array
      }

      data[dataLength] = '\0';                              // Terminate the char String (Add Null Terminating Char)

      return String(data);                                  // Return the Data.
    }

    /* Save Username to EEPROM */
    void EE_WriteUsername(String str)
    {
      byte len = str.length();                              // Get the String Length.
      int dataAddress = ADDR_USERNAME + 1;                  // Set the Initial Data Address

      EEPROM.update(ADDR_USERNAME, len);                    // Store the String Length to EEPROM

      for (int i = 0; i < len; i++)                         // Iterate over each char in String.
      {
        EEPROM.update(dataAddress + i, str[i]);             // Assign each char from Received String to an Address Position in EEPROM.
      }
    }
    #pragma endregion

    #pragma region <Computer Name>
    /* Get Computer Name from EEPROM */
    String EE_ReadComputername()
    {
      int dataLength  = EEPROM.read(ADDR_COMPUTERNAME);     // Get the Data Length from EEPROM Address Position.
      int dataAddress = ADDR_COMPUTERNAME + 1;              // Data Initial Address on EEPROM

      char data[dataLength +1];                             // Assign the Array Length (+1 to Add the Null Terminating Char).

      for (int i = 0; i < dataLength; i++)                  // Retrieve Data (Char by Char) by Iterating over EEPROM Address Positions.
      {
        data[i] = EEPROM.read(dataAddress + i);             // Add EEPROM Address Char to Array
      }

      data[dataLength] = '\0';                              // Terminate the char String (Add Null Terminating Char)

      return String(data);                                  // Return the Data.
    }

    /* Save Computer Name to EEPROM */
    void EE_WriteComputername(String str)
    {
      byte len = str.length();                              // Get the String Length.
      int dataAddress = ADDR_COMPUTERNAME + 1;              // Set the Initial Data Address

      EEPROM.update(ADDR_COMPUTERNAME, len);                // Store the String Length to EEPROM

      for (int i = 0 ; i < len; i++)                        // Iterate over each char in String.
      {
        EEPROM.update(dataAddress + i, str[i]);             // Assign each char from Received String to an Address Position in EEPROM.
      }
    }
    #pragma endregion

    #pragma region <Brightness>
    int EE_ReadBrightness()
    {
      return EEPROM.read(ADDR_BRIGHTNESS);
    }

    void EE_WriteBrightness(int val)
    {
      EEPROM.update(ADDR_BRIGHTNESS, val);
    }
    #pragma endregion


message:
Sending analog sensor data to laptop at 1kHz via USB

I am reading analog sensor data using Arduino nano, and the required sampling rate is around 1kHz. I am using the AnalogReadSerial example provided by Arduino with a delay of 1ms, so I am expecting to get around 1000 samples per second or slightly less due to the ADC conversion delay. However, the maximum number of samples I am able to get in my laptop a little bit less than 200 samples per seconds. I have tried increasing the baud rate to 115200 but that was not helpful. Am I missing something here, or is there something I need to do to get my data at the required sampling rate?

Below is AnalogReadSerial code I used for reference:

```
// the setup routine runs once when you press reset:
void setup() {
  // initialize serial communication at 9600 bits per second:
  Serial.begin(115200);
}

// the loop routine runs over and over again forever:
void loop() {
  // read the input on analog pin 0:
  int sensorValue = analogRead(A0);
  // print out the value you read:
  Serial.println(sensorValue);
  delay(1);        // delay in between reads for stability
}
```

body:
As I said in a comment, your code on my Uno gives me
791.5 samples/s. This is about 1263 µs per sample:

* about 110 µs for `analogRead()`, including 104 µs for the
  conversion proper
* presumably 1000 µs for `delay(1)`
* 153 µs for the rest of the code, mostly formatting `sensorValue`
  in ASCII

According to these timings, if it were not for the call to `delay()`,
the Arduino should be able to complete the loop in one millisecond, and
still have 737 µs to spare. The simplest way to achieve this is to
follow the [Blink Without Delay][] strategy:

```c++
void loop() {
    static uint32_t last_conversion_time = micros();
    if (micros() - last_conversion_time >= 1000) {
        last_conversion_time += 1000;
        Serial.println(analogRead(A0));
    }
}
```

This does give me 1000 samples per second. Note that
`last_conversion_time` is updated by adding 1000 µs rather than
setting it to `micros()`, so this is actually a variation on the Blink
Without Delay strategy. Updating `last_conversion_time` in this fashion
ensures that whenever the program gets late and misses the exact
microsecond it wanted, the small timing errors do not accumulate.

For the maximum possible timing accuracy, it would be more appropriate
to trigger the ADC by a timer, but that approach is more complex and
requires carefully reading the datasheet of the microcontroller.

[Blink Without Delay]: https://docs.arduino.cc/built-in-examples/digital/BlinkWithoutDelay


message:
Can I configure an Arduino via NFC using PN532 with an iPhone as the source?

It seems clear that Apple has intentionally limited the possibilities with NFC, so I understand that I'm going against the grain here. However, I need to support Android and Apple for my device setup, so I'm hoping to work around the Apple restrictions by making my Arduino receive data from an iPhone by posing as an RFID card and accepting a write from my Adafruit PN532 breakout board. I've got my Arduino Uno connected to the board and successfully reading from RFID cards. So the question is can I do a read from an iPhone? I've been experimenting with NFCTools on my iPhone to see if I can stimulate any behavior on my Arduino by running the Adafruit example programs and putting my phone near the reader while activating a write. I haven't had any success yet.

My idea is to avoid requiring Bluetooth for Arduino setup. My configuration is very simple so I don't need anything with high bandwidth. The configuration is done rarely and always by a person who is nearby. It seems like leaving out Bluetooth capability out of my device will save on cost and power consumption (though I don't know how much). It would be really slick too since my customer wouldn't need to go into settings to connect with Bluetooth. Instead they just put their phone near the device and it gets configured!

body: My understanding is that the PN532 is a reader/writer and will only want to communicate with passive nfc devices (an RFID card). Therefore, with a phone you cannot really communicate between the two in the way you want. Basically both your phone and the PN532 are going to only look for a passive device.


message:
Matrix Keyboard

I'm trying to program a mechanical keyboard running on the Arduino Pro Micro (5V/16MHz). I'm using a matrix approach (4x12), and while I believe the code and the wiring (both of which I've checked multiple times) are correct, I can't get the first two rows to work no matter what. I've tried wiring it up to other pins, which works, but only for two rows at a time, when I hook up all the 4 rows, the two ones on top don't work. The code:

```lang-cpp
/*cols and rows*/
byte rows[] = {2,3,4,5};
const int row_Count = 4;
byte cols[] = {6,7,8,9,10,14,15,16,18,19,20,21};
const int col_Count = 12;

byte keyboard[col_Count][row_Count];

void read_layout() {
    /*do the columns*/
    for (int col_Index=0; col_Index < col_Count; col_Index++) {
        /*setup for registering the column state*/
        byte cur_Col = cols[col_Index];
        pinMode(cur_Col, OUTPUT);
        digitalWrite(cur_Col, LOW);

        /*do the rows*/
        for (int row_Index=0; row_Index < row_Count; row_Index++) {
            byte row_Col = rows[row_Index];
            pinMode(row_Col, INPUT_PULLUP);
            keyboard[col_Index][row_Index] = digitalRead(row_Col);
            pinMode(row_Col, INPUT);
        }
        /*disable the column*/
        pinMode(cur_Col, INPUT);
    }
}

void print_layout() {
    for (int row_Index=0; row_Index < row_Count; row_Index++) {
        Serial.print(row_Index);
        Serial.print(F(": "));

        for (int col_Index=0; col_Index < col_Count; col_Index++) {
            Serial.print(keyboard[col_Index][row_Index]);
            if (col_Index < col_Count) Serial.print(F(", "));
        }
        Serial.println("");
    }
    Serial.println("");
}

void setup() {
    Serial.begin(115200);
    delay(2000);
    /*init the rows*/
    for(int i=0; i<row_Count; i++) {
        pinMode(rows[i], INPUT);
    }
    /*init the cols*/
    for (int i=0; i<col_Count; i++) {
        pinMode(cols[i], INPUT_PULLUP);
    }
}

void loop() {
    read_layout();
    print_layout();

}
```

This is the schematic, a "dirty sketch":
[![schematic][1]][1]

  [1]: https://archive.is/aOstH/91e28281c0bde7117145dfd7ffe3f5778a0801dd.png

body:
You are using the diodes in series, which leads to accumulating forward voltages in the lower rows of your schematic. Because of this accumulation the threshold for "low" will not be crossed, and the input pin cannot recognize a pressed key.

Instead, you should adopt this circuit (copied from ["Keyboard Matrix Help"][1] by Dave Dribin). Of course, you will put the cathods on your columns pins, and the anodes on the keys.

[![schematic][2]][2]

So the right circuit uses each diode-and-key combination in parallel, not in series.

  [1]: https://www.dribin.org/dave/keyboard/one_html/
  [2]: https://i.stack.imgur.com/ySxUr.png


message:
Why is the value of this uint32_t always 0?

Setting up a method to calculate ID3 frame sizes, but the variable *frsz* always returns 0. I need to pass this variable back to another method so the program can loop through the ID3 frames.

    void frameInfo(File track, char frame[4], uint32_t ltwo[4], int32_t frsz) {
     uint8_t buff[4];
     track.seek(10);
     track.read((uint8_t *)frame, 4);

     track.seek(14);
     track.read((uint8_t *)buff,4);
     ltwo[0] = buff[0];
     ltwo[1] = buff[1];
     ltwo[2] = buff[2];
     ltwo[3] = buff[3];

     ltwo[0] = ltwo[0] * 2097152;
     ltwo[1] = ltwo[1] * 16384;
     ltwo[2] = ltwo[2] * 128;

     frsz = ltwo[0] + ltwo[1] + ltwo[2] + ltwo[3];

     track.rewind();
    }

Am I missing some sort of initialization for this uint32?

body:
    void frameInfo(File track, char frame[4], uint32_t ltwo[4], int32_t frsz) {

The way you did it, frsz is passed by value (ie. a copy is made, and you have changed the copy, not the original). To make it change outside the function you need to pass it by reference:

    void frameInfo(File track, char frame[4], uint32_t ltwo[4], int32_t &frsz) {

Note the ampersand.


message:
using RTC for storage

I keep seeing stuff about this: https://www.arduino.cc/reference/en/libraries/rtcvars/ when looking for storage for a few variables that survive turning off and on, but then it is only on ESP8266.

The thing I am trying to understand is what it has to do with the RTC..  Other RTCs don't seem to have this arbitrary storage ability. Is the RTC in an ESP8266 nothing like any other RTC? Or is this really just some other storage on the chip? And what is the storage technology itself? If I am using an arduino uno, or just at avr chip, is there any unit I can attach that is or isn't part of an RTC with the same storage properties? Or does every RTC have this ability, and just need somebody to write the library?

According to this https://forum.arduino.cc/t/save-data-in-nonvolatile-memory/140801/2, the RTC memory of the the ESP8266 can be written to an infinite number of times, whereas an SD card will wear out if you update a value on it every second (like for a counter).

What technology is this "RTC memory" using that I can attach to my avr project?

body:
Some RTC chips contain a small amount of battery-backed SRAM ("NVRAM" - Non-Volatile RAM) which you can use for whatever you like. This is just ordinary RAM which is powered by the small battery that keeps the RTC running.

Not all do, though, so check the specs for your chosen RTC chip.

For example, the [DS1302](https://datasheets.maximintegrated.com/en/ds/DS1302.pdf) has:

> 31 x 8 Battery-Backed General-Purpose RAM

That's 31 bytes of storage you can use for what you like.

Conversely the [DS3231](https://datasheets.maximintegrated.com/en/ds/DS3231.pdf) doesn't have any spare RAM at all.


message:
Arduino u8glib Problem

I am Trying to make tetris on a 128x64 oled 1.3", and I am using the u8glib library. Here Is My Code:
```
#include "U8glib.h"

U8GLIB_SH1106_128X64 u8g(13, 11, 10, 9);

int val = -53;
int val2 = -53;

void setup() {
  // put your setup code here, to run once:
  Serial.begin(9600);
 // u8g.firstPage();
  //draw();
}

static const uint8_t PROGMEM tetris1 [] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
};

static const uint8_t PROGMEM tetris2 [] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
};

void draw() {
  u8g.drawBitmapP(val, 41, 16, 64, tetris1);
}

void d() {

}
void draw2() {
 u8g.firstPage();
 do {
  u8g.drawBitmapP(val2, 41, 16, 64, tetris2);
  val2 += 1;
  delay(250);
 }while(u8g.nextPage());
}

void loop() {
  // put your main code here, to run repeatedly:
  u8g.firstPage();
  do {
    draw();
  }while (u8g.nextPage());
  draw2();
}
```
The Problem is that when I call draw2() it creates a new page only displaying the shape from function draw2(), but what I want is for the shape from function draw() to stay there. Is there anyway I can do this??

body:
Most monochrome LCDs and operate on a principle of "pages". A page in this context is not a whole screen, but one strip of pixels, often 8 pixels high.

U8G draws the screen using these strips. It iterates over the whole screen on a page-by-page basis (a strip at a time, that is) and draws the content. Any drawing functions within that iterative loop (between `u8g.firstPage()` and the last `u8g.nextPage()`) get called for each strip and only the portion that is within the strip being drawn will be rendered.

This of course overwrites everything else on the screen. To display something it has to be within this loop of drawing each page. If you draw something in one loop then draw something else in another loop the second loop will overwrite what was there already.

This also means that you should not do anything other than drawing in a page loop. No delays, no complex calculations, etc. You want that loop to operate as fast as possible. Do any calculations outside the loop then run the loop. This is why the loop is often separated out into its own "draw" function, so you do all your work, then "draw" it to the screen.

So to draw two tetris pieces both those pieces have to be rendered within the same `.firstPage()` ... `.nextPage()` loop.


message:
Arduino Array Scope with SPI

when I try the following code the SPI works correctly (see oscilloscope plot)
```
#include <SPI.h>

void setup() {
  SPI.begin();
}

void loop() {
  SPI.beginTransaction(SPISettings(100000, MSBFIRST, SPI_MODE3));
  byte a[] = {0xC,0xFF,0xFF,0xFF};
  SPI.transfer(a, 4);
  SPI.endTransaction();
  delay(10);
}
```
[![enter image description here][1]][1]

However when I move the array declaration to the a global it doesn't work any more. (see next oscilloscope plot) Why is this?
```
#include <SPI.h>

byte a[] = {0xC,0xFF,0xFF,0xFF};

void setup() {
  SPI.begin();
}

void loop() {
  SPI.beginTransaction(SPISettings(100000, MSBFIRST, SPI_MODE3));
  SPI.transfer(a, 4);
  SPI.endTransaction();
  delay(10);
}
```
[![enter image description here][2]][2]

  [1]: https://i.stack.imgur.com/MmI1n.png
  [2]: https://i.stack.imgur.com/JnNgx.png

body:
When you call `SPI.transfer(a, 4);`, any "received data" is stored in your byte array, `a[]`. The original data is overwritten.

If you print out the contents of the array before and after the function call to `SPI.transfer()`, you will see in the serial monitor what is happening to your array contents.

Here are 2 test sketches to illustrate the difference between the array with a global scope, VS the one with a static scope.

**Global Scope**

```c++
// Sketch uses 2344 bytes (7%) of program storage space.
// Global variables use 193 bytes (9%) of dynamic memory.
#include <SPI.h>

byte a[] = {0xC,0xFF,0xFF,0xFF};

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

void loop() {
  SPI.beginTransaction(SPISettings(100000, MSBFIRST, SPI_MODE3));
  for(int i = 0; i < 4; i++){
    Serial.print(a[i]);
  }
  Serial.println();
  SPI.transfer(a, 4);
  SPI.endTransaction();
  for(int i = 0; i < 4; i++){
    Serial.print(a[i]);
  }
  Serial.println('\n');
  delay(1000);
}
```

**Static Scope**

```c++
// Sketch uses 2410 bytes (7%) of program storage space.
// Global variables use 193 bytes (9%) of dynamic memory.
#include <SPI.h>

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

void loop() {
  SPI.beginTransaction(SPISettings(100000, MSBFIRST, SPI_MODE3));
  byte a[] = {0xC,0xFF,0xFF,0xFF};
  for(int i = 0; i < 4; i++){
    Serial.print(a[i]);
  }
  Serial.println();
  SPI.transfer(a, 4);
  SPI.endTransaction();
  for(int i = 0; i < 4; i++){
    Serial.print(a[i]);
  }
  Serial.println('\n');
  delay(1000);
}

```

The following sketch should solve the problem. Using the `const` keword before the declaration of the `b[]` array is optional.

```c++
// Sketch uses 2436 bytes (7%) of program storage space.
// Global variables use 197 bytes (9%) of dynamic memory.
#include <SPI.h>
const byte b[] = {0xC,0xFF,0xFF,0xFF};

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

void loop() {
  SPI.beginTransaction(SPISettings(100000, MSBFIRST, SPI_MODE3));
  byte a[] = {0xC,0xFF,0xFF,0xFF};
  for(int i = 0; i < 4; i++){
    Serial.print(a[i]);
  }
  Serial.println();
  SPI.transfer(a, 4);
  SPI.endTransaction();
  memcpy(a, b, sizeof(b));
  for(int i = 0; i < 4; i++){
    Serial.print(a[i]);
  }
  Serial.println('\n');
  delay(1000);
}

```

One last edit. The compile size can be reduced by 66 bytes thanks to the `static` keyword.

```c++
// Sketch uses 2370 bytes (7%) of program storage space.
// Global variables use 197 bytes (9%) of dynamic memory.
#include <SPI.h>
const byte b[] = {0xC,0xFF,0xFF,0xFF};

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

void loop() {
  SPI.beginTransaction(SPISettings(100000, MSBFIRST, SPI_MODE3));
  static byte a[] = {0xC,0xFF,0xFF,0xFF};
  for(int i = 0; i < 4; i++){
    Serial.print(a[i]);
  }
  Serial.println();
  SPI.transfer(a, 4);
  SPI.endTransaction();
  memcpy(a, b, sizeof(b));
  for(int i = 0; i < 4; i++){
    Serial.print(a[i]);
  }
  Serial.println('\n');
  delay(1000);
}
```

 For more information, see: [Arduino.cc][1]

  [1]: https://www.arduino.cc/en/Reference/SPITransfer