message:
Problems lighting LEDs on receiving Arduino given a char array from sending Arduino in Tinkercad

The gist of the problem is that I'm trying to have an Arduino with a breadboard that has 5 buttons and 4 LEDs each led is linked with a button and the fifth button "sends" the lights that were switched on with a char array to the receiving Arduino, in this Arduino, this Arduino algo has a breadboard with 4 LEDs of the same color and with the char array I try to switch the same LEDs that were switched on in the first Arduino, my problem is when I send the char array and receive it in the second Arduino and try to run a function that runs through the array and find which points in the char array are different than 0 and turn on a led it never turns any LEDs, I know the logic is right but I don't understand why it doesn't work.

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

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

This is the design I am working with in tinkercad and will also link the project if you wish to run it on there, I assume that the problem is from tinkercad and not the code though I may be horribly wrong.

This is the sender sketch
`````
#include <SoftwareSerial.h>

#define rxPin 9
#define txPin 8

// Iniciamos los pins de los 4 leds de sender y reciver
const int ledRed = 13;
const int ledBlue = 12;
const int ledGreen = 11;
const int ledWhite = 10;

// iniciamos los pins de los 5 botones
const int pushbuttonRed = 7;
const int pushbuttonBlue = 6;
const int pushbuttonGreen = 5;
const int pushbuttonWhite = 4;
const int pushbuttonEnviar = 3;

// Declaramos el estado de los 4 leds de sender y reciver
int ledStateRed = 0;
int ledStateBlue = 0;
int ledStateGreen = 0;
int ledStateWhite = 0;

char c;
char leds[7] = {'H','0','0','0','0','F','\0'};

//String cadena_final = "";
SoftwareSerial receiver =  SoftwareSerial(rxPin, txPin);

void setup() {
  pinMode(rxPin, INPUT);
  pinMode(txPin, OUTPUT);
  Serial.begin(9600);
  receiver.begin(9600);
  pinMode(ledRed, OUTPUT);
  pinMode(ledBlue, OUTPUT);
  pinMode(ledGreen, OUTPUT);
  pinMode(ledWhite, OUTPUT);
  pinMode(pushbuttonRed, INPUT);
  pinMode(pushbuttonBlue, INPUT);
  pinMode(pushbuttonGreen, INPUT);
  pinMode(pushbuttonWhite, INPUT);
  pinMode(pushbuttonEnviar, INPUT);
}

void loop() {

    // Boton Rojo
 if(digitalRead(pushbuttonRed) == 1) {
      digitalWrite(ledRed, HIGH);
      ledStateRed += 1;
      leds[1] = '1';
      if(ledStateRed % 2 == 0){
        digitalWrite(ledRed, LOW);
        leds[1] = '0';
        ledStateRed = 0;
      }
      delay(100);
   }

   // Boton Azul
   if(digitalRead(pushbuttonBlue) == 1) {
      digitalWrite(ledBlue, HIGH);
      ledStateBlue += 1;
      leds[2] = '1';
      if(ledStateBlue % 2 == 0){
        digitalWrite(ledBlue, LOW);
        ledStateBlue = 0;
        leds[2] = '0';
      }
      delay(100);
   }

   // Boton Verde
   if(digitalRead(pushbuttonGreen) == 1) {
      digitalWrite(ledGreen, HIGH);
      ledStateGreen += 1;
      leds[3] = '1';
      if(ledStateGreen % 2 == 0){
        digitalWrite(ledGreen, LOW);
        ledStateGreen = 0;
        leds[3] = '0';
      }
      delay(100);
   }

   // Boton Blanco
   if(digitalRead(pushbuttonWhite) == 1) {
      digitalWrite(ledWhite, HIGH);
      ledStateWhite += 1;
      leds[4] = '1';
      if(ledStateWhite % 2 == 0){
        digitalWrite(ledWhite, LOW);
        ledStateWhite = 0;
        leds[4] = '0';
      }
      delay(100);
   }

   // Boton Enviar
   if(digitalRead(pushbuttonEnviar) == 1) {
      // Reinicio los leds de sender para enviar otro mensaje
      ledStateWhite = 0;
      ledStateGreen = 0;
      ledStateBlue = 0;
      ledStateRed  = 0;
      digitalWrite(ledWhite, LOW);
      digitalWrite(ledRed, LOW);
      digitalWrite(ledBlue, LOW);
      digitalWrite(ledGreen, LOW);
      delay(100);
      Serial.write(leds,7);
      leds[1] = '0';
      leds[2] = '0';
      leds[3] = '0';
      leds[4] = '0';
   }
}

void printArray(char A[]){
  int i = 0;
   for(i=0;i<6;i++){
    Serial.print(A[i]);
    }
}

`````

This is the receiver sketch
`````
#include <SoftwareSerial.h>

#define rxPin 9
#define txPin 8

char leds2[7] = {'\0'};

// Iniciamos los pins de los 4 leds
const int Red = 4;
const int Blue = 5;
const int Green = 6;
const int White = 7;

// Creamos el boton que limpia pantalla
const int buttonClear = 10;

char c;
String recData;

SoftwareSerial receiver =  SoftwareSerial(rxPin, txPin);

void setup() {
  pinMode(rxPin, INPUT);
  pinMode(txPin, OUTPUT);
  receiver.begin(9600);
  pinMode(Red, OUTPUT);
  pinMode(Blue, OUTPUT);
  pinMode(Green, OUTPUT);
  pinMode(White, OUTPUT);

  Serial.begin(9600);
}

void loop() {
  int i=0;

    if (receiver.available()) {

      delay(100); //allows all serial sent to be received together
      while(receiver.available() && i<6) {
        leds2[i] = receiver.read();   // starts with i=0
        delay(100);
        i++;
      }
      leds2[i]='\0';
      //digitalWrite(Red,HIGH);
    }
    if(i>0) {
      lightLeds(leds2);
    }
}

void lightLeds(char A[]){
   int i;

   for(i=0;i<6;i++){
      if(A[1]=='1' || A[1]==1) digitalWrite(Red, HIGH);
       if(A[2]=='1' || A[2]==1) digitalWrite(Blue, HIGH);
       if(A[3]=='1' || A[3]==1) digitalWrite(Green, HIGH);
       if(A[4]=='1' || A[4]==1) digitalWrite(White, HIGH);
    }
}

void printArray(char A[]){
  int i = 0;
   for(i;i<6;i++){
    Serial.print(A[i]);
    }
}

`````

body:
Your "working logic" is quite unlogic:

In sender you define a char array:

   char leds[6] = {'H','0','0','0','0','F'};

which should be

     char leds[7] = {'H','0','0','0','0','F','\0'}; // terminate the array

Here each '0' represents a led as can be seen in subroutine `Boton Enviar`
Instead of assigning a state to each position 0/1 so leds[2]='1' would be e.g. led blue ON you write a number to it (example walk through for blue):

    if(digitalRead(pushbuttonBlue) == 1) {
          digitalWrite(ledBlue, HIGH);
          ledStateBlue += 1;
          leds[2] = '5';  // Here should be leds[2] = '1';
          if(ledStateBlue % 2 == 0){
            digitalWrite(ledBlue, LOW);
            ledStateBlue = 0;
            leds[2] = '0';

so if blue and and you send (if using the terminator)

     leds[] = {'H','5','0','0','0','F'.'\0'};

On the receiver side the following happens:

       while(receiver.available() && i<6) {
            leds2[i++] = receiver.read();   // starts with i=1
            delay(100);
          }
          leds2[i++]='\0';
          digitalWrite(Red,HIGH);
        }
        if(i>0) {
          lightLeds(leds2);

 so your led2 looks like

     {XX,'H','5','0','0','0','F'} //XX is undefined garbage might be '\0' so the array ends here

Solution define array as follows:

    char leds2[7] ={'\0'};
    .....
       while(receiver.available() && i<6) {
            leds2[i] = receiver.read();   // starts with i=0
            delay(100);
            i++;
          }
          leds2[i]='\0';
          // digitalWrite(Red,HIGH); // USE builtin led not one of the used as "end marker"
        }
        if(i>0) {
          lightLeds(leds2)

The light logic should go for the space a value is and not the value:

    void lightLeds(char A[]){
        int i;

        for(i=0;i<6;i++){
            if(A[2]=='1' || A[2]==1) digitalWrite(Blue, HIGH);
            if(A[2]=='0' || A[2]==0) digitalWrite(Blue, LOW);
           ....
        }
    }

 To get the mix of different logics apart place both progs in an editor (eg. notepad++) side by side and look for differences in the logic. There is more than one error in the programs, fix them as proposed and it wll work (Read the comments in my code for further details).

**EDIT**

The OP had still problems with his code. I tookthe example and let it run hardware based on two UNOs, it worked but SoftwareSerial is very bad. No problem on the hardware with AltSoftSerial.h. In TinkerCAD no chance, the moment I switched to HW-Serial it worked like a charm, so here is the refined code for SENDER:

    // Time variables
    unsigned long startTime = 0;
    unsigned long intervalTime = 1000; // send once a second

    // Iniciamos los pins de los 4 leds de sender y reciver
    const int ledRed = 13;
    const int ledBlue = 12;
    const int ledGreen = 11;
    const int ledWhite = 10;

    // iniciamos los pins de los 5 botones
    const int pushbuttonRed = 7;
    const int pushbuttonBlue = 6;
    const int pushbuttonGreen = 5;
    const int pushbuttonWhite = 4;
    const int pushbuttonEnviar = 3;

    // Declaramos el estado de los 4 leds de sender y reciver
    int ledStateRed = 0;
    int ledStateBlue = 0;
    int ledStateGreen = 0;
    int ledStateWhite = 0;

    char c;
    char leds[7] = {'H', '0', '0', '0', '0', 'F', '\0'};

    //String cadena_final = "";
    SoftwareSerial sender =  SoftwareSerial(rxPin, txPin);

    void setup() {
      pinMode(ledRed, OUTPUT);
      pinMode(ledBlue, OUTPUT);
      pinMode(ledGreen, OUTPUT);
      pinMode(ledWhite, OUTPUT);
      pinMode(pushbuttonRed, INPUT);
      pinMode(pushbuttonBlue, INPUT);
      pinMode(pushbuttonGreen, INPUT);
      pinMode(pushbuttonWhite, INPUT);
      pinMode(pushbuttonEnviar, INPUT);
      sender.begin(19200);
      DEBUG_INTERFACE.begin(9600);
      DEBUG_INTERFACE.println("DEBUG ON");
    }

    void loop() {

      // Boton Rojo
      if (digitalRead(pushbuttonRed) == 1) {
        digitalWrite(ledRed, HIGH);
        ledStateRed += 1;
        leds[1] = '1';
        if (ledStateRed % 2 == 0) {
          digitalWrite(ledRed, LOW);
          leds[1] = '0';
          ledStateRed = 0;
        }
      }

      // Boton Azul
      if (digitalRead(pushbuttonBlue) == 1) {
        digitalWrite(ledBlue, HIGH);
        ledStateBlue += 1;
        leds[2] = '1';
        if (ledStateBlue % 2 == 0) {
          digitalWrite(ledBlue, LOW);
          ledStateBlue = 0;
          leds[2] = '0';
        }
      }

      // Boton Verde
      if (digitalRead(pushbuttonGreen) == 1) {
        digitalWrite(ledGreen, HIGH);
        ledStateGreen += 1;
        leds[3] = '1';
        if (ledStateGreen % 2 == 0) {
          digitalWrite(ledGreen, LOW);
          ledStateGreen = 0;
          leds[3] = '0';
        }
      }

      // Boton Blanco
      if (digitalRead(pushbuttonWhite) == 1) {
        digitalWrite(ledWhite, HIGH);
        ledStateWhite += 1;
        leds[4] = '1';
        if (ledStateWhite % 2 == 0) {
          digitalWrite(ledWhite, LOW);
          ledStateWhite = 0;
          leds[4] = '0';
        }
      }

      // Boton Enviar
      if (digitalRead(pushbuttonEnviar) == 1) switchAll();

        if (millis() - startTime > intervalTime) {
        DEBUG_INTERFACE.println(leds);
        sender.println(leds);
        startTime = millis();
      }
    }

    void switchAll() {
      // Reinicio los leds de sender para enviar otro mensaje
      ledStateWhite = 0;
      ledStateGreen = 0;
      ledStateBlue = 0;
      ledStateRed  = 0;
      digitalWrite(ledWhite, LOW);
      digitalWrite(ledRed, LOW);
      digitalWrite(ledBlue, LOW);
      digitalWrite(ledGreen, LOW);
      DEBUG_INTERFACE.println(leds);
      leds[1] = '0';
      leds[2] = '0';
      leds[3] = '0';
      leds[4] = '0';
    }

and the code for RECEIVER:

    // Iniciamos los pins de los 4 leds
    const int Red = 4;
    const int Blue = 5;
    const int Green = 6;
    const int White = 7;

    // Creamos el boton que limpia pantalla
    const int buttonClear = 10;

    char rc;
    const int maxChar = 6;
    static byte charCount = 0;
    char leds2[7] = {'\0'};
    bool newData = false;

    #define DEBUG_INTERFACE Serial
    #define receiver Serial

    void setup() {
      receiver.begin(9600);
      pinMode(Red, OUTPUT);
      pinMode(Blue, OUTPUT);
      pinMode(Green, OUTPUT);
      pinMode(White, OUTPUT);

      DEBUG_INTERFACE.begin(9600);
      DEBUG_INTERFACE.println("DEBUG ON");
    }

    void loop() {
      receiveStartEndMarkers();
      if (newData) {
        DEBUG_INTERFACE.print(" LED Array received: ");
        DEBUG_INTERFACE.println(leds2);
        lightLeds(leds2);
        newData = false;
      }
    }

    void lightLeds(char A[]) {
      for (int i = 0; i < 6; i++) {
        if (A[1] == '1' || A[1] == 1) digitalWrite(Red, HIGH);
        if (A[2] == '1' || A[2] == 1) digitalWrite(Blue, HIGH);
        if (A[3] == '1' || A[3] == 1) digitalWrite(Green, HIGH);
        if (A[4] == '1' || A[4] == 1) digitalWrite(White, HIGH);
        if (A[1] == '0' || A[1] == 0) digitalWrite(Red, LOW);
        if (A[2] == '0' || A[2] == 0) digitalWrite(Blue, LOW);
        if (A[3] == '0' || A[3] == 0) digitalWrite(Green, LOW);
        if (A[4] == '0' || A[4] == 0) digitalWrite(White, LOW);
      }
      DEBUG_INTERFACE.print(A); DEBUG_INTERFACE.println(" Leds switched");
    }

    void receiveStartEndMarkers() {
      static boolean recvInProgress = false;
      char startMarker = 'H';
      char endMarker = 'F';

      if (receiver.available() > 0) {
        rc = receiver.read();
        //DEBUG_INTERFACE.print(rc);
        if (recvInProgress) {
          if (rc != endMarker) {
            leds2[charCount] = rc;
            charCount++;
            if (charCount > maxChar) {
              charCount = maxChar;
            }
          }
          else {
            leds2[charCount] = rc;
            charCount++;
            leds2[charCount] = '\0'; // terminate the string
            recvInProgress = false;
            charCount = 0;
            newData = true;
          }
        }
        else if (rc == startMarker) {
          recvInProgress = true;
          leds2[charCount] = rc;
          charCount++;
        }
      }
    }

Working code looks like this - change to HW-Serial 0(RX), 1(TX) to 1(TX), 0(RX):

[![enter image description here][1]][1]
So as a result **DO NOT USE SoftwareSerial.h in TinkerCAD** - its not working at the moment, use HW serial for communication examples or you will get crazy if working code suddenly outputs garbagge. When using real hardware use AltSoftSerial (full duplex mode). If you plan to use your design with real hardware use resistors for the LEDs (search for resistor calculator LED) as different colored leds need different resistor values.

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


sender: user

message:
Terminal read-only serial monitor without blocking serial port for sketch upload

I would like to have all serial output from Arduino (nano) dumped to the terminal in Linux, without blocking the serial port for uploading new sketch version (for quick debugging loop), when using [Arduino-Makefile](https://github.com/sudar/Arduino-Makefile):

    [Errno 16] could not open port /dev/ttyUSB0: [Errno 16] Device or resource busy: '/dev/ttyUSB0'

Is there something made for that already? I did read about 10 related questions here and elsewhere (using `screen`, `socat` and others) but none of them deals with the question how to not block the port.

I might eventually code something in Python, which will disconnect when  signalled and reconnect again after a few seconds (I use custom Makefile for the upload) and I imagine Arduino's IDE serial monitor does something similar.

Other pointers on how to solve the issue are appreciated!

sender: assistant

body:
You can write your own python script that prints received serial output. By using try/except in a loop you can "pause" your serial monitor while uploading is in progress.

I did the same a while ago using `pyserial` on linux. I'd like to share it, but at the moment I have no access to my other machine. I can post it later if you want.


body:
> (using screen, socat and others) but none of them deals with the question how to not block the port.

> Other pointers on how to solve the issue are appreciated!

I say:

> Virtually all hardware problems can be solved with software. But, sometimes, the $50000 software problem can be solved with the $2 hardware solution.

This is one of those cases. [Buy a CP2102 6-pin serial UART USB adapter for < $2 on Ebay][1], or [for < $10 on Amazon][2], to provide a second serial interface to the same Arduino (both connected to the same hardware UART built in to the Arduino's ATmega328 mcu). Let the main USB serial interface handle code uploads to the Arduino. Let this 2nd, external UART handle READ-ONLY from the Arduino!

Plug it in:

    Arduino     CP2102 USB 6-pin UART
    -------     ---------------------
    Tx          Rx
    GND         GND

Done. Do NOT plug in the CP2102 `Tx` to anything.

Now, use [`picocom`](https://github.com/npat-efault/picocom) (one of my favorites), `screen`, or [my crude datalogging Python serial terminal I wrote here (eRCaGuy_PyTerm)](https://github.com/ElectricRCAircraftGuy/eRCaGuy_PyTerm), or a 2nd instance of the Arduino IDE with the Serial Monitor, or any other serial terminal for that matter, to read from the CP2102 while the Arduino's built-in USB adapter does code uploading.

Two serial interfaces to the same pins on the Arduino: one does Tx/Rx to/from the Arduino, while the other does only Rx to read from the Arduino.

I use a 2nd UART like this all the time as a trick to allow me to read the data from the Arduino into one **Serial Monitor** in one instance of the Arduino IDE so I can _see the numbers,_ and I use the external CP2101 USB adapter to _read the same exact data from the Arduino_ into the **Serial Plotter** of another instance of the Arduino IDE so I can see the _live, plotted graphs!_

It's amazing how well this works. Quick hack. Easy solution.

----

Note: to you use my [eRCaGuy_PyTerm](https://github.com/ElectricRCAircraftGuy/eRCaGuy_PyTerm) Python serial terminal, first set all your serial parameters inside the `user_config.py` file, then run `python3 serial_terminal.py` to run the program. It is a 2-way serial terminal, _with datalogging_. It works quite well. I really should improve its readme and post some examples someday.

  [1]: https://www.ebay.com/sch/i.html?_from=R40&_trksid=p2380057.m570.l1313&_nkw=serial uart 6 pin&_sacat=0
  [2]: https://amzn.to/33JB1Jf


message:
activate a relay with two esp8266 -12e pins

I have an esp8266-12e that I want to activate the reset side of a latching relay.  The problem is that the 12e only puts out 12mA/pin and the relay needs more than that.  I am using a transistor on the set side from a rf antenna signal.  I only have one 3.3v power source.  Is there a way to have two pins go HIGH at the exact same time and be connected to the reset side of the relay so there is enough current?  Would this work, would it hurt anything, and how would I write the code for it and how would I wire it up?

I have tried the code where one pin is written HIGH right after the other like this

```
digitalWrite (5,HIGH);
digital Write (6,HIGH);
```
but I think pin 5 goes of before pin 6.
Any way to get them to go off at the same time?

Thanks for the help

body:
That is not a good idea.

Isolating the relay from the IO pin is not just about the current limit of an IO pin, it's also about preventing back-EMF spikes from the relay coil(s) from damaging the delicate internals of the chip.

Instead you *must* at least use a transistor and a back-EMF protecting diode.

However - if you *did* want to theoretically have two pins *safely* controlled to provide double the current (though I stress again, do *not* do this for driving a relay), it is possible.

But it's not straight forward.

It's not possible on the ESP8266 to use port manipulation to make two pins change state at the same time. However it is possible to go *via a third state* that makes it safe.

**Note: this will only be "safe" for IO pins that do not do strange things at bootup, and many of the pins on the ESP8266 do strange things.**

IO pins actually have three states, not two:

* High
* Low
* High Impedance

The latter is the state the pin is in when in INPUT mode. And we can use that to our advantage.

When in High Impedance mode it's like the pin is disconnected.  So we could:

1. Make sure both pins are in INPUT mode
2. Switch one pin to OUTPUT and set it to the desired state
3. Switch it back to INPUT mode (keeping the desired state latched)
4. Switch the other pin to OUTPUT and set it to the desired state
5. Set the first pin back to OUTPUT mode again.

This can be slightly compressed as we don't really need to set both pins to INPUT at the start, only one.  So here's some code that might do it:

```
void digitalDoubleWrite(int pina, int pinb, bool level) {
    pinMode(pina, INPUT);
    pinMode(pinb, OUTPUT);
    digitalWrite(pinb, level);
    pinMode(pinb, INPUT);
    pinMode(pina, OUTPUT);
    digitalWrite(pina, level);
    pinMode(pinb, OUTPUT);
}
```

You might ask why we'd want to switch to OUTPUT just to latch a level into the pin. Well, that's because of a quirk of the Arduino API. A historical artefact that is lingering in there to this day:

* `digitalWrite()` on a pin set to INPUT mode was used to turn the internal pullup resistor on and off

It's actually how the AVR's IO ports control the pullup resistors internally, and that has most often been copied in software for other chips to maintain backward compatibility with old code. So as a result we have to switch to OUTPUT mode so that the API code knows that we mean to set the output latch state and not the pullup resistor state.


message:
How to use DO pin on ldr module?

I have ldr module with 4 pins
 1. Vin
 2. Gnd
 3. AO
 4. DO

I want to know how can i take advantage of DO suppose i want to turn on lcd display when light falls on the ldr sensor!

[![enter image description here][1]][1]
I have noticed when light falls on ldr sensor the Green  led with DO written next to it lights up.

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

body:
The DO pin gives a Digital Output that is HIGH when the light falling on the LDR is above a threshold, and LOW when it's below a threshold. Just connect it to a digital input pin and read that pin with `digitalRead()`.

You can change the threshold by adjusting the small blue trimpot.


message:
Timer Accuracy Always off by 1uS

I am using the ATMega32u4 to generate a pulse at 1 kHz. I am using Timer 3, which is a 16-bit timer and using a prescaler of 1, so I have a 0.0625uS resolution. The good news is that this is working, I can control the frequency and pulse length of the square wave. The issue is that I noticed the pulse always seems to be 1uS off.

If I set a period of 1000uS, and a pulse of 500uS, the oscilloscope shows a period of 1001uS and a pulse of 501uS.

If I set a period of 100uS, and pulse of 10uS, the oscilloscope shows a period of 101uS, and a pulse of 11uS.

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

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

If the Timer had an error percentage, then both the period and pulse should be off by the same percentage, but there are always off by the same 1uS length. I assume I am doing something wrong, so I have posted my code below.

    const int pin1 = 4;

    void setup() {
      //Set pin to output
      pinMode(pin1, OUTPUT);

      // Reset Timer 3 Control Register to 0
      TCCR3A = 0;

      // Set prescaler to 1
      TCCR3B &= ~(1 << CS32); //0
      TCCR3B &= ~(1 << CS31); //0
      TCCR3B |= (1 << CS30);  //1

      //Reset Timer 3 and set compare value
      TCNT3 = 0;

      // Enable Timer 3 compare interrupt A and B
      TIMSK3 |= (1 << OCIE3B);
      TIMSK3 |= (1 << OCIE3A);

      //Enable global interrupts
      sei();

      //Set Refresh Rate
      OCR3A = 1000;
      OCR3B = 100 / 0.0625;
    }

    void loop() {
      delay(100);
    }

    ISR(TIMER3_COMPA_vect) {
      PORTD &= ~_BV(pin1); //LOW
      OCR3A = 160;
    }

    ISR(TIMER3_COMPB_vect) {
      TCNT3 = 0;
      PORTD |= _BV(pin1); //HIGH
    }

  [1]: https://i.stack.imgur.com/sWAcq.png
  [2]: https://i.stack.imgur.com/l1HFG.png

body:
The problem is here:

```c++
ISR(TIMER3_COMPB_vect) {
  TCNT3 = 0;
  ...
```

If you want to get anything that vaguely looks like accurate timings,
you should **never** reset the timer. The MCU needs time to process an
interrupt: it has to save the program counter to the stack, load the
address of the interrupt vector, execute it (it's typically a jump),
save all the registers it needs to the stack, and only then can it start
executing the code you wrote in the ISR. From your experiment, it looks
like all this process takes about 1 µs. But don't take this delay
for granted: from time to time the interrupt will fire while the MCU is
processing another interrupt, and this will increase the latency.

You have two options:

1. Update the compare registers in order to program the next interrupts
   some time in the future. In this case, the COMPB ISR would do
   `OCR3A = OCR3B + 160; OCR3B += 1600;`. Do not worry about the
   overflows: they do the Right Thing.

2. Let the timer reset itself to zero: it will then do so without
   loosing a single cycle. See the CTC and fast PWM modes of the timer.

For your specific use case, PWM seems like the obvious choice. Not only
will the timer handle the resetting itself, it can also generate the
output signal without requiring you to write any ISR. Beware that in
this case the period of the signal is whatever you load in corresponding
compare register _plus one_, and the duration of the pulse is another
compare register _plus one_.

As a side note:

```c++
  // Reset Timer 3 Control Register to 0
  TCCR3A = 0;
```

I would also reset `TCCR3B`. The Arduino core configures both registers
for it's own purposes, so it would be safer to clear them both.


message:
PC8563 Arduino interface

i am trying to interface pc8563 with arduino uno . I have small doubt related to RTC slave address reading

RTC datasheet says page no 14
where device slave address is A2 for write and Read A3
i would like to know how A2 /A3

Example code from website device id mentioned as 0X51

**My question how to config exact slave address ??**

    #include "Wire.h"
    #define PCF8563address 0x51

    byte second, minute, hour, dayOfWeek, dayOfMonth, month, year;
    String days[] = {"Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday" };

    byte bcdToDec(byte value)
    {
      return ((value / 16) * 10 + value % 16);
    }

    byte decToBcd(byte value){
      return (value / 10 * 16 + value % 10);
    }

    void setPCF8563()
    // this sets the time and date to the PCF8563
    {
      Wire.beginTransmission(PCF8563address);
      Wire.write(0x02);
      Wire.write(decToBcd(second));
      Wire.write(decToBcd(minute));
      Wire.write(decToBcd(hour));
      Wire.write(decToBcd(dayOfMonth));
      Wire.write(decToBcd(dayOfWeek));
      Wire.write(decToBcd(month));
      Wire.write(decToBcd(year));
      Wire.endTransmission();
    }

    void readPCF8563()
    // this gets the time and date from the PCF8563
    {
      Wire.beginTransmission(PCF8563address);
      Wire.write(0x02);
      Wire.endTransmission();
      Wire.requestFrom(PCF8563address, 7);
      second     = bcdToDec(Wire.read() & B01111111); // remove VL error bit
      minute     = bcdToDec(Wire.read() & B01111111); // remove unwanted bits from MSB
      hour       = bcdToDec(Wire.read() & B00111111);
      dayOfMonth = bcdToDec(Wire.read() & B00111111);
      dayOfWeek  = bcdToDec(Wire.read() & B00000111);
      month      = bcdToDec(Wire.read() & B00011111);  // remove century bit, 1999 is over
      year       = bcdToDec(Wire.read());
    }

    void setup()
    {
      Wire.begin();
      Serial.begin(9600);
      // change the following to set your initial time
      second = 0;
      minute = 28;
      hour = 9;
      dayOfWeek = 2;
      dayOfMonth = 13;
      month = 8;
      year = 13;
      // comment out the next line and upload again to set and keep the time from resetting every reset
      setPCF8563();
    }

    void loop()
    {
      readPCF8563();
      Serial.print(days[dayOfWeek]);
      Serial.print(" ");
      Serial.print(dayOfMonth, DEC);
      Serial.print("/");
      Serial.print(month, DEC);
      Serial.print("/20");
      Serial.print(year, DEC);
      Serial.print(" - ");
      Serial.print(hour, DEC);
      Serial.print(":");
      if (minute < 10)
      {
        Serial.print("0");
      }
      Serial.print(minute, DEC);
      Serial.print(":");
      if (second < 10)
      {
        Serial.print("0");
      }
      Serial.println(second, DEC);
      delay(1000);
    }

[RTC datasheet][1]

  [1]: https://www.nxp.com/docs/en/data-sheet/PCF8563.pdf

body:
Normal I2C addresses are 7-bit long. On the first frame of an I2C
transaction, the master sends an 8-bit byte containing the address of
the slave followed by a bit specifying whether this is a read or a write
operation. Some people tend to call “address” the whole 8-bit frame,
which causes confusion. Because of this, we end up having three flavors
of I2C addresses:

 * the 7-bit address, which is the real device address
 * the 8-bit “write address”, which is the address followed by a 0
   meaning “write operation”
 * the 8-bit “read address”, which is the address followed by a 1
   meaning “read operation”

For your RTC, the 3 addresses are the following, in hex and binary:

    7-bit = 0x51 = 0b1010001
    write = 0xA2 = 0b10100010
    read  = 0xA3 = 0b10100011

The Arduino Wire library expects the 7-bit address.


message:
HID communication between Arduino Uno and computer

I used some firmware I found online to turn the UNO into an emulated HID device. The Arduino is no longer connected to a Serial COM port so I can't send serial data from my computer to the device. Is there a way that the Arduino can receive data from the computer in order to drive a function while in the HID emulated state?

body: You could use a second USB on the PC and use Hardware Serial to transmit commands. (Either via a second Arduino or a FTDI adapter)<br> But be aware that at least the [firmware I use](https://github.com/NicoHood/HID) and the controller programs are very sensitive to being disturbed in the loop. So you should have a good understanding of timers, interupts and non blocking code.


message:
Wire.endTransmission() hangs, but only, if wire.begin(); is called with an address (MKR WiFi 1010)

This code runs without issues, scoped and seen from serial output:
```
#include <Wire.h>

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

  while (!Serial);
}

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

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

This one hangs on Wire.endtransmission():

```
#include <Wire.h>

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

  while (!Serial);
}

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

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

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

body:
> I want to push data from the slaves to the master immediately when they receive said data.

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

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

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


body:
While the wire library supports multi-master for AVR, it doesn't for ATSAMD.

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


message:
5 arrays or one matrix?

I am working on a project where i need to store as fast I can following :

1 - Acceleration on X

2 - Acceleration on Y

3 - Acceleration on Z

4 - timestamp

5 - A value from some other sensor

Because I need to get these as fast as I can I am thinking to not do any calculation while acquire values and just store them for 30 -60 seconds and then when the "test" is complete to compute calculations.
My question is if will be better to create 5 arrays and put these values there or create a matrix and store values there.
I need these values to be stored like they are "connected"
e.g. on reading 1 i get 5 values and put them on array[0] , then on reading 1 and so on
Also an important thing to mention, this will run on a esp32.

Thank you

body:
I fully agree with Edgar Bonet.

My opinion is keeping a 'matrix' is better, or actually one array (of structs), where each array elements stores all information for one measurement (which is stored inside one struct). This has some benefits:

- Data of one measurement is consecutive in memory, so you can easily transfer it (to some external memory or sending it). It's exact one struct (and you can use `sizeof(struct_item)` to know how many bytes you have to transfer.

- It's good practice in general to keep information together, creating 5 always-equal length arrays seems strange.
- If for some reason you want to make a single array dynamic or change it to a ring buffer for example, you can easily add/remove items (instead of dynamically changing 5 arrays).
- Locality of change (see comments of Kwasmich/DuncanC)

There is also one benefit about having separate arrays (where each array stores one type of information, like an acceleration or timestamp: when you have a function (especially in another class) that only needs one of them, you can specifically send that array (or pointer/reference), so the other information is hidden from that function.


message:
Vin & VU pins of NodeMCU V3

Can we use the vin pin of the lolin v3 nodeMCU as a 5V supply. If yes, i checked mine with a multimeter. At max, it gives a voltage of 2V. Is my pin blown out? Also, can use the VU pin as a 5V supply? Will using it cause any problems to my laptop's USB port? Can somebody help me out?

I need 5V to drive a relay using the v3

body:
On the NodeMCU “v3” (and only on the v3) there’s a pin called VU (Vusb) that is connected to the +5V on the USB bus of the NodeMCU socket. This pin can be used to feed external components when it’s connected to USB, within the limits of the USB power supply it’s connected to.

The Vin pin (which is available on all NodeMCUs (and not just the v3) is a +5V power *input* which can be used to power the NodeMCU if it is not connected to USB. It can not be used as an output and it needs a stabilized supply.


message:
With the press of a button, I need to play an intro sound file, then one of 50 other sounds in order, each time a button is pressed

I need to play an intro file and one of 50 different files after it in order each time the switch is pressed, with a short delay between the intro and next file.

For example let's say the intro is called "intro.wav," and each of the 50 other sound files are just named 01.wav-50.wav.

The logic would be:

```
TRIGGER
PLAY intro.wav
250ms DELAY
PLAY 01.wav
END
```

```
TRIGGER
PLAY intro.wav
250ms DELAY
PLAY 02.wav
END
```

```
TRIGGER
PLAY intro.wav
250ms DELAY
PLAY 03.wav
END
```
and so on, until all 50 files are played, then start over.

The messages are going to be a curated group of words. I'm not sure what the intro will be yet, but it will just be something like:

intro.wav = "The word of the day is"

01.wav = "help"

02.wav = "climb"

03.wav = "think"

I'm looking for some guidance on where to start with this, if an Arduino product would be suitable, and if so, which one.  I've worked with the Adafruit Audio FX Sound Board before, and that can *almost* do what I need it to do, but not by itself. It looks like I'll need an Arduino of some kind to accomplish this, so I went ahead ordered an Uno.

I'm not married to the idea of having the intro and word files separate either. If I need to create all 50 files to contain the intro and the word, that would be fine, as long as each one is triggered sequentially.

In that scenario, 01.wav could be "The word of the day is ... help" and the button would basically be the "next track" command.  I don't really have a problem with doing that because I'm all about keeping things simple and I don't think I'd run out of space, but I think it would be less time consuming to just dump all the individual word files onto the card.

The important thing is that the track(s) would play once, then stop, and when the button is pressed again, the next one plays.

body:
You will find all the code and thelibrary you need on the [Adafruit learn center](https://learn.adafruit.com/adafruit-audio-fx-sound-board/serial-audio-control).<br>
For such a project I would use a DF-robot (clone) MP3 player (~4$), an Uno, a speaker and an SD card. The [library for the player](https://github.com/DFRobot/DFRobotDFPlayerMini) includes examples to get you started and the sound project you plan is possible even with low programming skills. Look at the example codes provided and start to program.


message:
Swap two arrays (using pointers, not copy)

I've got two arrays, defined as:

    uint8_t array1[10];
    uint8_t array2[10];

I'd like to swap the arrays (actually the pointers to each array) using code like this:

    uint8_t *tmp = array1;
    array1 = array2;
    array2 = tmp;

However, I keep getting errors like:

    invalid array assignment

for the last two lines. I don't recall this being such a problem in traditional C++. I've tried all sorts of casting to no avail. Is there something I'm missing?

I can get the code to run properly if I switch the declarations for the arrays to use `new` and have them just be more-or-less pointers rather than arrays, but I'd rather not have to do that:

    uint8_t *array1 = new uint8_t[10];
    uint8_t *array2 = new uint8_t[10];

Code is running on an ARM-based SAMD51 (Cortex M4 processor).

Thanks for any tips!

body:
Figured it out. Though using `new` works, I wanted to keep the buffers out of the heap. The following declarations work with the swap code:

    uint8_t a1[10];
    uint8_t a2[10];
    uint8_t *array1 = a1;
    uint8_t *array2 = a2;

    uint8_t *tmp = array1;
    array1 = array2;
    array2 = tmp;


message:
Need help with using pulseInLong to time a sensor

I have a setup consisting of a magnet suspended above a sensor coil. It acts as a pendulum and creates a ~ 4 mV signal when it swings over the coil - this goes through two stages of an LM358 to generate a 5V signal. The signal is very messy with lots of 'ringing'
This signal is fed into pin A0 of an Arduino Uno. I used MegunoLink.h and Filter.h which is an exponential filter library then applied constrain and map, finally converting to a clean 0 - 400 (units?) square wave of about 1 second with a varying duty cycle. This is the information I want as it tells me that the magnet is homing in on the sensor (the duty cycle increases as it gets close).
But when I apply pulseInLong I only get a string of zeros on the serial monitor.
What am I doing wrong?
Here is the sketch:
```
//  Coding by Jeremy 130520
//  further development for ricochet module
//https://www.megunolink.com/documentation/arduino-libraries/exponential-filter/
//https://www.google.com/search?q=how+to+use+arduino+pulsein

#include "MegunoLink.h"
#include "Filter.h"
// Create a new exponential filter with a weight of 5 and an initial value of 0.
ExponentialFilter<long> ADCFilter(5, 0);

int coilPin = 8;
int analogIn = A0;
unsigned long pulseLength;
unsigned long signal_1;

void setup()
{
  pinMode(coilPin, OUTPUT);
  pinMode(analogIn,INPUT);
  Serial.begin(9600);
  }

void loop()
{
 int RawValue = analogRead(analogIn);
  ADCFilter.Filter(RawValue);
 signal_1 =(ADCFilter.Current());
 signal_1 = constrain(signal_1,80, 200);
 signal_1 = map(signal_1, 80, 200,0,400);
 if (signal_1 >= 200) {signal_1 = 400; digitalWrite(coilPin, HIGH);}
 if (signal_1 < 200) {signal_1 = 0; digitalWrite(coilPin, LOW);}

 Serial.println(signal_1); //using the plotter

//pulseLength = pulseInLong(coilPin, HIGH);
 //Serial.println(pulseLength);
 delay(10);
}
```
[![changed duty cycle][1]][1]

[![output at end][2]][2]

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

body:
You cannot use `pulseInLong()` because it is a _blocking function_. It
waits until the input rises, then waits until it falls again, and only
then it returns a value. While it's waiting, the rest of the program
cannot run. This means you will not be able to actually generate the
signal you are trying to time.

The easiest solution is to time things yourself with `micros()`. You
have to implement an _edge detector_, i.e. some logic that remembers the
previous state of the signal and notices when it changes:

```c++
static bool is_high;  // is the input currently HIGH?
static uint32_t time_of_rise;  // when did it rise?

if (!is_high && signal_1 >= 200) {  // rising edge
    time_of_rise = micros();
    is_high = true;
} else if (is_high && signal_1 < 200) {  // falling edge
    uint32_t pulse_width = micros() - time_of_rise;
    is_high = false;
    Serial.println(pulse_width);
}
```


message:
How do I set a variable so that after a condition is met the loop ignores input?

I have a analog inputs to my Uno that I am cleaning up and using to keep a digital pin high until the output drops to zero. At this point I want to stop reading that input because it may come back up after being low for a short time.
Is there any way to set a variable that can be triggered by that first zero that prevents the loop from sending the digital pin high from then on?
Like a latch of some sort, or could I use an interrupt somehow?

body:
You've already described what you need to do.  Just set a boolean variable.  It really couldn't be easier.

    boolean runThisPart = true;

    void loop() {

      if(runThisPart) {
         // this part only runs if runThisPart is true
         //  if something happens and you don't want
         //  to run this part anymore then
         if(some-condition){
            runThisPart = false;
         }
      }
      //  The rest of your code can also set runThisPart
      //  to true or false to turn that section on or off.
    }


message:
Is it possible to count rising edges of a 4 MHz clock on an Arduino Due and trigger an interrupt like all 4'000'000 edges?

I am struggling with my Arduino Due and the Timer Counter functionallity. The following is what I am trying to achieve:

I want to execute a function to a specific point of time or more precisley after a specific amount of rising edges given by an external clock signal with a frequency of approx. 4 MHz. Thus I read the Atmel Datasheet, Section 36, Timer Counter. My approach was to trigger an interrupt every rising edge and increment a counter variable until I reached the desired amount of rising edges and call my function then. I can confirm that I am in fact counting rising edges with my current approach but I am reading way too slow. Is there any kind of register or hardware counter which automates the counting process. Like I set the register to a specific value and wait for an overflow, execute my function and reset the register? From my web research I found that this is possible on the Uno and Mega but I could not find anything for the Due and to be honest I am a bit overwhelmed by the Atmel Datasheet. Why not just use an Arduino Due or Mega then? I need the 3.3 Volts of the Due and from what I found the Uno and Mega are 5 V devices.

This is my code:

```

// define capture channels
#define CAPTURE_TC TC0
#define CAPTURE_CHANNEL 0
#define CAPTURE_IRQn TC0_IRQn
#define CAPTURE_Handler TC0_Handler
#define CAPTURE_ID ID_TC0
#define CAPTURE_PIN 2
#define CAPTURE_CLOCK_SELECTION TC_CMR_TCCLKS_TIMER_CLOCK3

// clock divisors corresponding to CAPTURE_CLOCK_SELECTION
static const uint32_t divisors[5] = { 2, 8, 32, 128, 0};

volatile uint32_t captured_pulses = 0;
volatile uint32_t captured_ra = 0;
volatile uint32_t captured_rb = 0;
volatile float frequency, duty_cycle, active_time;

/*
* Function:  setup
* ------------------------------------------------------------------------------
* Setup code. Will be executed once.
*/
void setup() {

  // init serial connection
  Serial.begin(115200);
  Serial.print("Initializing...");

  // configure the PIO pin as peripheral
  const PinDescription *config = &g_APinDescription[CAPTURE_PIN];
  PIO_Configure(config->pPort, config->ulPinType, config->ulPin, config->ulPinConfiguration);

  // enable timer peripheral clock
  pmc_enable_periph_clk(CAPTURE_ID);

  // configure the timer
  TC_Configure(CAPTURE_TC, CAPTURE_CHANNEL,
    CAPTURE_CLOCK_SELECTION   // Clock Selection
    | TC_CMR_LDRA_RISING      // RA Loading: rising edge of TIOA
    | TC_CMR_LDRB_FALLING     // RB Loading: falling edge of TIOA
    | TC_CMR_ABETRG           // External Trigger: TIOA
    | TC_CMR_ETRGEDG_FALLING  // External Trigger Edge: Falling edge
 );

  // configure TC interrupts
  NVIC_DisableIRQ(CAPTURE_IRQn);
  NVIC_ClearPendingIRQ(CAPTURE_IRQn);
  NVIC_SetPriority(CAPTURE_IRQn, 0);
  NVIC_EnableIRQ(CAPTURE_IRQn);

  // enable interrupts
  CAPTURE_TC->TC_CHANNEL[CAPTURE_CHANNEL].TC_IER = TC_IER_LDRBS;

  // start timer counter
  CAPTURE_TC->TC_CHANNEL[CAPTURE_CHANNEL].TC_CCR = TC_CCR_CLKEN | TC_CCR_SWTRG;

  Serial.println("ready!");

} // setup

/*
* Function:  loop
* ------------------------------------------------------------------------------
* Loop code. Will be executed repeatedly after setup completed.
*/
void loop() {

 // Serial.print("Captured rising edges: "); Serial.println(captured_ra);
} // loop

/*
* Function:  CAPTURE_Handler
* ------------------------------------------------------------------------------
*
*/
void CAPTURE_Handler() {
 if ((TC_GetStatus(CAPTURE_TC, CAPTURE_CHANNEL) & TC_SR_LDRBS) == TC_SR_LDRBS) {
   captured_pulses++;
   // captured_ra = CAPTURE_TC->TC_CHANNEL[CAPTURE_CHANNEL].TC_RA;
   // captured_rb = CAPTURE_TC->TC_CHANNEL[CAPTURE_CHANNEL].TC_RB;

   if (captured_pulses == 4164303) {
    captured_pulses = 0;
    // specific_function_call();
   }
 }
} // CAPTURE_Handler
```

Thanks for your time, any help is grealty appreciated.

body:
First of all excuse my inactivity but as you know it's crazy times right now. However I finally figured it out, it's for sure not the most elegant solution but it meets my requirements. Thanks for your help @KamilCuk.

Here is my code if anyone may ever have the same problem as I did. External signal goes on Digital Pin 2. Works fine with a 4.2 MHz external clock.

```

// define capture channels
#define CAPTURE_TC TC0
#define CAPTURE_CHANNEL 0
#define CAPTURE_IRQn TC0_IRQn
#define CAPTURE_Handler TC0_Handler
#define CAPTURE_ID ID_TC0
#define CAPTURE_PIN 2
#define CAPTURE_CLOCK_SELECTION TC_CMR_TCCLKS_TIMER_CLOCK3

/*
* Function:  setup
* ------------------------------------------------------------------------------
* Setup code. Will be executed once.
*/
void setup() {

  // init serial connection
  Serial.begin(115200);
  Serial.print("Initializing...");

  // configure the PIO pin as peripheral
  const PinDescription *config = &g_APinDescription[CAPTURE_PIN];
  PIO_Configure(config->pPort, config->ulPinType, config->ulPin, config->ulPinConfiguration);

  // enable timer peripheral clock
  pmc_enable_periph_clk(CAPTURE_ID);

  // configure the timer
  TC_Configure(CAPTURE_TC, CAPTURE_CHANNEL,
    CAPTURE_CLOCK_SELECTION   // Clock Selection
    | TC_CMR_LDRA_RISING      // RA Loading: rising edge of TIOA
    | TC_CMR_ABETRG           // External Trigger: TIOA
    | TC_CMR_CPCTRG           // RC Compare
  );

  // configure TC interrupts
  NVIC_DisableIRQ(CAPTURE_IRQn);
  NVIC_ClearPendingIRQ(CAPTURE_IRQn);
  NVIC_SetPriority(CAPTURE_IRQn, 0);

  // enable interrupts and start counter
  CAPTURE_TC->TC_CHANNEL[CAPTURE_CHANNEL].TC_IER = TC_IER_CPCS;                  // enable RC Compare Interrupt
  CAPTURE_TC->TC_CHANNEL[CAPTURE_CHANNEL].TC_CCR = TC_CCR_CLKEN | TC_CCR_SWTRG;  // the datasheet said I need this
  NVIC_EnableIRQ(CAPTURE_IRQn);                                                  // enable interrupts

  // set the trigger value for RC_Compare
  CAPTURE_TC->TC_CHANNEL[CAPTURE_CHANNEL].TC_RC = 4164303;

  Serial.println("ready!");

} // setup

/*
* Function:  loop
* ------------------------------------------------------------------------------
* Main code. Will be executed repeatedly.
*/
void loop() {

} // loop

/*
* Function:  CAPTURE_Handler respectively TC0_Handler
* ------------------------------------------------------------------------------
* Timer capture trigger. Will be executed if TC0_RA == TC0_RC
*/
void CAPTURE_Handler() {
  // reset status register
  TC_GetStatus(CAPTURE_TC, CAPTURE_CHANNEL);

  // do something
  Serial.println("Trigger");
  // function_call()
}
```


message:
How to power 6 servo motors using battery to create a robotic arm?

I am trying to create a robotic arm. The problem is that I could not run all 6 servo motors -3 MG966r servo motors and 3 MG90S servo motors - simultaneously, using 12V and 3A AC to DC adaptor. Last time I tried, My arduino uno is totally broken. If you can, Could you provide the schematics for the circuit? or Is there any methods to solve this problem?. Also Is it a better idea to use servo motor shield?

body:
For this task you should use an extra power supply not running trough the Arduino. For this kind of setup I use PCA9865 16-channel servo dirver board cost around 5$, needs two pins only and can run all servos (strong 5V power supply provided => Amperage) simultaniously. For a max of 8 servos a 5V/2-2.5A power supply (wall wart) should be sufficient.<br>
See this example circuit for how to connect:
[![PCA9685-Schematic][1]][1]

The [PCA9865 library has examples](https://github.com/adafruit/Adafruit-PWM-Servo-Driver-Library) how to drive servos via program. As this board is an I/O board you could also attach joystick(s) or buttons to it to save pins on your board.

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


message:
How to use USB-in on an arduino?

I'm trying to use an arduino as a controller adapter. How would I get USB-in to get the signal from a usb video game controller?

body:
It makes actually no sense to plug an USB-Controller via an Arduino to a PC. The direct way and using an autofire/macro /custom key programmer app is more efficient.<br>

 - The Arduino UNO (with 32u4) can either replace an USB controller as [demostrated in NicoHood HID library](https://github.com/NicoHood/HID) or
 - additionally act as an interface for controller with strange vendor specific plugs [demostrated in UNOJOY](https://github.com/AlanChatham/UnoJoy) and you can build your own Controller/interface out of nearly every old non usb controller by cutting the hardware specific plug (e.g. old Xbox) and attach to an UNO who acts as "interface" to the PC. Another example is a [C64-Joystick to the PC](https://create.arduino.cc/projecthub/fpfaffendorf/commodore-64-joystick-usb-adapter-c64joy-fc2389)
 - The other option for using an Arduino is interfacing with "old video game systems" . For some there are already more or less succesfull projects. When connecting the USB controller via an USB shield you have normally a high lag time due to the USB shield library, so the better approach is to cut the USB plug and directly interface with the Arduino.

Project with USB Host-shield:

 - [C64 - with USB Joysticks](https://create.arduino.cc/projecthub/DocSnyderde/connect-usb-joystick-to-commodore-c64-2fb5ba)

Project old Joystick to USB-PC:

 - [NES controller to PC USB](https://www.allaboutcircuits.com/projects/nes-controller-interface-with-an-arduino-uno/)

Project Arduino as controller for NES/SNES:

 - [UNO to NES/SNES](https://github.com/jtrinklein/SConE)

Info on the [pinout/protocol cn be found in this page](https://github.com/dfanara/NESDuino)


message:
Why can the Xbox360 not detect the Arduino Leonardo as keyboard?

Arduino Leonardo as keyboard in the computer works! But not with the Xbox360.
The Teensy works perfectly on the PC but how to emulate a keyboard device for the Xbox360.

I know the Xbox360 has security IC, but a simple USB keyboard works!

What is the diference ?

How i can emulate an usb keyboard for the Xbox360?

body:
Like Juraj and Majenko said. Arduino Keyboard library does emulate "Boot Keyboard".

I use [NicoHood HID library][1] and now it works.

  [1]: https://github.com/NicoHood/HID


message:
Arduino AES encryption, working example or tutorial

I am quite new to idea of encryption and am trying to use aes-256-ecb encryption.
 I am using library called "Arduino cryptography". Unfortunately I could not find any tutorial that would explain how to encrypt a json string (and other things latter) using a  key.

I have a function that generates same key on both sides of Arduino and php script on a server side, but I could not find a working tutorial (except the case of obsolete buggy library with instruction like : "copy this text" and even that doesn't work.
Unfortunately libraries examples do not bother to show how to retrieve  encrypted string or explain what is what and instead just focus on checking how long encryption takes.

Does any of you know of some tutorial or an example from which I could engineer a solution?
library link:[The library][1]

in buioltin example there is a code of:
```
cipher->decryptBlock(buffer, test->ciphertext);
```
But I do not understand where is the output and where the input here

Second  question would be if I can use other modes like the mentioned GCM simply by changing the value in
```
static TestVector const testVectorAES256 = {
    .name        = "AES-256-ECB",
    .key         = {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
                    0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
                    0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
                    0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F},
    .plaintext   = {0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77,
                    0x88, 0x99, 0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF},
    .ciphertext  = {0x8E, 0xA2, 0xB7, 0xCA, 0x51, 0x67, 0x45, 0xBF,
                    0xEA, 0xFC, 0x49, 0x90, 0x4B, 0x49, 0x60, 0x89}
};
```
or how?

  [1]: https://rweather.github.io/arduinolibs/index.html

After bits and strougles I have managed to get this working, but next step is how to make it take a string:
```
/*Skúška kódovania GCM-AES256#*/

#include <Crypto.h>
#include <AES.h>
#include <GCM.h>
//#include <pgmspace.h>

struct TestVector
{
    const char *name;
    uint8_t key[32];
    uint8_t plaintext[60];
    uint8_t ciphertext[60];
    uint8_t authdata[20];
    uint8_t iv[12];
    uint8_t tag[16];
    size_t authsize;
    size_t datasize;
    size_t tagsize;
    size_t ivsize;
};

static TestVector const testVectorGCM PROGMEM = {
    .name        = "AES-256 GCM",
    .key         = {0xfe, 0xff, 0xe9, 0x92, 0x86, 0x65, 0x73, 0x1c,
                    0x6d, 0x6a, 0x8f, 0x94, 0x67, 0x30, 0x83, 0x08,
                    0xfe, 0xff, 0xe9, 0x92, 0x86, 0x65, 0x73, 0x1c,
                    0x6d, 0x6a, 0x8f, 0x94, 0x67, 0x30, 0x83, 0x08},
    .plaintext   = {0xd9, 0x31, 0x32, 0x25, 0xf8, 0x84, 0x06, 0xe5,
                    0xa5, 0x59, 0x09, 0xc5, 0xaf, 0xf5, 0x26, 0x9a,
                    0x86, 0xa7, 0xa9, 0x53, 0x15, 0x34, 0xf7, 0xda,
                    0x2e, 0x4c, 0x30, 0x3d, 0x8a, 0x31, 0x8a, 0x72,
                    0x1c, 0x3c, 0x0c, 0x95, 0x95, 0x68, 0x09, 0x53,
                    0x2f, 0xcf, 0x0e, 0x24, 0x49, 0xa6, 0xb5, 0x25,
                    0xb1, 0x6a, 0xed, 0xf5, 0xaa, 0x0d, 0xe6, 0x57,
                    0xba, 0x63, 0x7b, 0x39},
    .ciphertext  = {0x52, 0x2d, 0xc1, 0xf0, 0x99, 0x56, 0x7d, 0x07,
                    0xf4, 0x7f, 0x37, 0xa3, 0x2a, 0x84, 0x42, 0x7d,
                    0x64, 0x3a, 0x8c, 0xdc, 0xbf, 0xe5, 0xc0, 0xc9,
                    0x75, 0x98, 0xa2, 0xbd, 0x25, 0x55, 0xd1, 0xaa,
                    0x8c, 0xb0, 0x8e, 0x48, 0x59, 0x0d, 0xbb, 0x3d,
                    0xa7, 0xb0, 0x8b, 0x10, 0x56, 0x82, 0x88, 0x38,
                    0xc5, 0xf6, 0x1e, 0x63, 0x93, 0xba, 0x7a, 0x0a,
                    0xbc, 0xc9, 0xf6, 0x62},
    .authdata    = {0xfe, 0xed, 0xfa, 0xce, 0xde, 0xad, 0xbe, 0xef,
                    0xfe, 0xed, 0xfa, 0xce, 0xde, 0xad, 0xbe, 0xef,
                    0xab, 0xad, 0xda, 0xd2},
    .iv          = {0xca, 0xfe, 0xba, 0xbe, 0xfa, 0xce, 0xdb, 0xad,
                    0xde, 0xca, 0xf8, 0x88},
    .tag         = {0x76, 0xfc, 0x6e, 0xce, 0x0f, 0x4e, 0x17, 0x68,
                    0xcd, 0xdf, 0x88, 0x53, 0xbb, 0x2d, 0x55, 0x1b},
    .authsize    = 20,
    .datasize    = 60,
    .tagsize     = 16,
    .ivsize      = 12
};

TestVector testVector;
byte buffer[128];

bool testCipher_N(AuthenticatedCipher *cipher, const struct TestVector *test, size_t inc)
{
    size_t posn, len;
    uint8_t tag[16];

    crypto_feed_watchdog();

    cipher->clear();
    if (!cipher->setKey(test->key, cipher->keySize())) {
        Serial.print("setKey ");
        return false;
    }
    if (!cipher->setIV(test->iv, test->ivsize)) {
        Serial.print("setIV ");
        return false;
    }

    memset(buffer, 0xBA, sizeof(buffer));

    for (posn = 0; posn < test->authsize; posn += inc) {
        len = test->authsize - posn;
        if (len > inc)
            len = inc;
        cipher->addAuthData(test->authdata + posn, len);
    }

    for (posn = 0; posn < test->datasize; posn += inc) {
        len = test->datasize - posn;
        if (len > inc)
            len = inc;
        cipher->encrypt(buffer + posn, test->plaintext + posn, len);
    }

    Serial.println("Vystup:\n");
    for(uint8_t i=0; i<sizeof(buffer); i++) printf("0x%X,",buffer[i]);

    return true;
}

void testCipher(AuthenticatedCipher *cipher, const struct TestVector *test)
{
    bool ok;

    memcpy_P(&testVector, test, sizeof(TestVector));
    test = &testVector;

    Serial.print(test->name);
    Serial.print(" ... ");

    ok  = testCipher_N(cipher, test, test->datasize);
    /*ok &= testCipher_N(cipher, test, 1);
    ok &= testCipher_N(cipher, test, 2);
    ok &= testCipher_N(cipher, test, 5);
    ok &= testCipher_N(cipher, test, 8);
    ok &= testCipher_N(cipher, test, 13);
    ok &= testCipher_N(cipher, test, 16);*/

    if (ok)
        Serial.println("Passed");
    else
        Serial.println("Failed");
}

void perfCipherSetKey(AuthenticatedCipher *cipher, const struct TestVector *test, const char *name)
{
    unsigned long start;
    unsigned long elapsed;
    int count;

    crypto_feed_watchdog();

    memcpy_P(&testVector, test, sizeof(TestVector));
    test = &testVector;

    Serial.print(name);
    Serial.print(" SetKey ... ");

    start = micros();
    for (count = 0; count < 1000; ++count) {
        cipher->setKey(test->key, cipher->keySize());
        cipher->setIV(test->iv, test->ivsize);
    }
    elapsed = micros() - start;

    Serial.print(elapsed / 1000.0);
    Serial.print("us per operation, ");
    Serial.print((1000.0 * 1000000.0) / elapsed);
    Serial.println(" per second");
}

void perfCipherEncrypt(AuthenticatedCipher *cipher, const struct TestVector *test, const char *name)
{
    unsigned long start;
    unsigned long elapsed;
    int count;

    crypto_feed_watchdog();

    memcpy_P(&testVector, test, sizeof(TestVector));
    test = &testVector;

    Serial.print(name);
    Serial.print(" Encrypt ... ");

    cipher->setKey(test->key, cipher->keySize());
    cipher->setIV(test->iv, test->ivsize);
    start = micros();
    for (count = 0; count < 500; ++count) {
        cipher->encrypt(buffer, buffer, 128);
    }
    elapsed = micros() - start;

    Serial.print(elapsed / (128.0 * 500.0));
    Serial.print("us per byte, ");
    Serial.print((128.0 * 500.0 * 1000000.0) / elapsed);
    Serial.println(" bytes per second");
}

void setup(){
 Serial.begin(115200);
 Serial.println("Začínam\n");
 GCM <AES256> *gcm=0;
 gcm= new GCM<AES256>();
 gcm->setKey(testVectorGCM.key, 32);
 gcm->setIV(testVectorGCM.iv,testVectorGCM.ivsize);
 crypto_feed_watchdog();
 //gcm->encrypt(buffer,testVectorGCM.plaintext,60);
 testCipher(gcm,&testVectorGCM);
 delete gcm;
 //gcm.encrypt(&vstupny,&vystup,49);
 crypto_feed_watchdog();
    Serial.println("Vystup: \n");
    for(uint8_t i=0; i<50;i++) Serial.print(buffer[i]);
}

void loop(){
 delay(1000);
 Serial.print(".");
}
```
I need to be able to get the text on PHP side

body:
Kind of an answer. After the advise from @Kwasmich I have converted to aes-256-gcm.

Upgraded to UTF-8 thanks to Edgar Bonet

Based mostly on GCMTest example comming with Arduino Cryptograhy libraries:

-----------------------------------------------

**Shared between Encryption and decrition**

First need to define parts which will not change:

```
#include <Crypto.h>
#include <AES.h>
#include <GCM.h>

struct TestVector
{
    const char *name;
    uint8_t key[32];
    uint8_t authdata[20];
    uint8_t iv[12];
    uint8_t tag[16];
    size_t authsize;
    size_t tagsize;
    size_t ivsize;
};

static TestVector const testVectorGCM PROGMEM = {   //Dont forget to change the Values here
    .name        = "AES-256 GCM",
    .key         = {0xfe, 0xff, 0xe9, 0x92, 0x86, 0x65, 0x73, 0x1c,
                    0x6d, 0x6a, 0x8f, 0x94, 0x67, 0x30, 0x83, 0x08,
                    0xfe, 0xff, 0xe9, 0x92, 0x86, 0x65, 0x73, 0x1c,
                    0x6d, 0x6a, 0x8f, 0x94, 0x67, 0x30, 0x83, 0x08},
    .authdata    = {0xfe, 0xed, 0xfa, 0xce, 0xde, 0xad, 0xbe, 0xef,
                    0xfe, 0xed, 0xfa, 0xce, 0xde, 0xad, 0xbe, 0xef,
                    0xab, 0xad, 0xda, 0xd2},
    .iv          = {0xca, 0xfe, 0xba, 0xbe, 0xfa, 0xce, 0xdb, 0xad,
                    0xde, 0xca, 0xf8, 0x88},
    .tag         = {0x76, 0xfc, 0x6e, 0xce, 0x0f, 0x4e, 0x17, 0x68,
                    0xcd, 0xdf, 0x88, 0x53, 0xbb, 0x2d, 0x55, 0x1b},
    .authsize    = 20,
    .tagsize     = 16,
    .ivsize      = 12
};
```
Now create a global buffer (easier to understand then pointers)
```
TestVector testVector;
byte buffer[128];
```

**Encrytpion**

```void encrypt(AuthenticatedCipher *cipher, const struct TestVector *test, size_t datasize)
{
    memcpy_P(&testVector, test, sizeof(TestVector));   //Load into memory
    test = &testVector;
    size_t posn, len;
    uint8_t tag[16];
    crypto_feed_watchdog();    //To protect from Watchdog reseting this function
```
It is important to clear memory of any ciphering before doing one:
```
    cipher->clear();
```
```
    cipher->setKey(test->key, cipher->keySize());    //Setting key
    cipher->setIV(test->iv, test->ivsize);     //vector
    for (posn = 0; posn < test->authsize; posn += datasize) {
        len = test->authsize - posn;
        if (len > datasize)
            len = datasize;
        cipher->addAuthData(test->authdata + posn, len);   //To make hack even more confusing
    }
    Serial.print("input numbers ");
 for(uint8_t i=0; i<60; i++) Serial.printf("%X",buffer[i]);
 Serial.println();

    for (posn = 0; posn < datasize; posn += datasize) {
        len = datasize - posn;
        if (len > datasize) len = datasize;
        crypto_feed_watchdog();
        cipher->encrypt((uint8_t*)buffer + posn, buffer + posn, len); //This is why we are here
        crypto_feed_watchdog();
    }
    Serial.println("Vystup:\n");
    for(uint8_t i=0; i<sizeof(buffer); i++) printf("0x%X,",buffer[i]);
}
```

**Decryption**

```
void decrypt(AuthenticatedCipher *cipher, const struct TestVector *test, size_t datasize){
    bool ok;

    memcpy_P(&testVector, test, sizeof(TestVector));
    test = &testVector;
    size_t posn, len;
    uint8_t tag[16];
    crypto_feed_watchdog();
    cipher->clear();
    cipher->setKey(test->key, cipher->keySize());
    cipher->setIV(test->iv, test->ivsize);
    for (posn = 0; posn < test->authsize; posn += datasize) {
        len = test->authsize - posn;
        if (len > datasize)
            len = datasize;
        cipher->addAuthData(test->authdata + posn, len);
    }

    for (posn = 0; posn < datasize; posn += datasize) {
        len = datasize - posn;
        if (len > datasize)
            len = datasize;
        cipher->decrypt((uint8_t*)buffer + posn, buffer + posn, len);
    }

    Serial.print("\nVystup: ");
    for(uint8_t i=0; i<60;i++) Serial.printf("%c",(char)buffer[i]);
    Serial.println();

}
```

-----------------------------------------------

full example:
```
/*Skúška kódovania GCM-AES256#*/

#include <Crypto.h>
#include <AES.h>
#include <GCM.h>

struct TestVector
{
    const char *name;
    uint8_t key[32];
    uint8_t authdata[20];
    uint8_t iv[12];
    uint8_t tag[16];
    size_t authsize;
    size_t tagsize;
    size_t ivsize;
};

static TestVector const testVectorGCM PROGMEM = {
    .name        = "AES-256 GCM",
    .key         = {0xfe, 0xff, 0xe9, 0x92, 0x86, 0x65, 0x73, 0x1c,
                    0x6d, 0x6a, 0x8f, 0x94, 0x67, 0x30, 0x83, 0x08,
                    0xfe, 0xff, 0xe9, 0x92, 0x86, 0x65, 0x73, 0x1c,
                    0x6d, 0x6a, 0x8f, 0x94, 0x67, 0x30, 0x83, 0x08},
    .authdata    = {0xfe, 0xed, 0xfa, 0xce, 0xde, 0xad, 0xbe, 0xef,
                    0xfe, 0xed, 0xfa, 0xce, 0xde, 0xad, 0xbe, 0xef,
                    0xab, 0xad, 0xda, 0xd2},
    .iv          = {0xca, 0xfe, 0xba, 0xbe, 0xfa, 0xce, 0xdb, 0xad,
                    0xde, 0xca, 0xf8, 0x88},
    .tag         = {0x76, 0xfc, 0x6e, 0xce, 0x0f, 0x4e, 0x17, 0x68,
                    0xcd, 0xdf, 0x88, 0x53, 0xbb, 0x2d, 0x55, 0x1b},
    .authsize    = 20,
    .tagsize     = 16,
    .ivsize      = 12
};

TestVector testVector;
byte buffer[128];

void encrypt(AuthenticatedCipher *cipher, const struct TestVector *test, size_t datasize)
{
    memcpy_P(&testVector, test, sizeof(TestVector));
    test = &testVector;
    size_t posn, len;
    uint8_t tag[16];
    crypto_feed_watchdog();

    cipher->clear();
    cipher->setKey(test->key, cipher->keySize());
    cipher->setIV(test->iv, test->ivsize);
    for (posn = 0; posn < test->authsize; posn += datasize) {
        len = test->authsize - posn;
        if (len > datasize)
            len = datasize;
        cipher->addAuthData(test->authdata + posn, len);
    }
    Serial.print("Cisla: ");
 for(uint8_t i=0; i<60; i++) Serial.printf("%X",buffer[i]);
 Serial.println();

    for (posn = 0; posn < datasize; posn += datasize) {
        len = datasize - posn;
        if (len > datasize) len = datasize;
        crypto_feed_watchdog();
        cipher->encrypt((uint8_t*)buffer + posn, buffer + posn, len);
        crypto_feed_watchdog();
    }
    Serial.println("Vystup:\n");
    //  Decrypt
    for(uint8_t i=0; i<sizeof(buffer); i++) printf("0x%X,",buffer[i]);
}

void decrypt(AuthenticatedCipher *cipher, const struct TestVector *test, size_t datasize){
    bool ok;

    memcpy_P(&testVector, test, sizeof(TestVector));
    test = &testVector;
    size_t posn, len;
    uint8_t tag[16];
    crypto_feed_watchdog();
    cipher->clear();
    cipher->setKey(test->key, cipher->keySize());
    cipher->setIV(test->iv, test->ivsize);
    for (posn = 0; posn < test->authsize; posn += datasize) {
        len = test->authsize - posn;
        if (len > datasize)
            len = datasize;
        cipher->addAuthData(test->authdata + posn, len);
    }

    for (posn = 0; posn < datasize; posn += datasize) {
        len = datasize - posn;
        if (len > datasize)
            len = datasize;
        cipher->decrypt((uint8_t*)buffer + posn, buffer + posn, len);
    }

    Serial.print("\nVystup: ");
    for(uint8_t i=0; i<60;i++) Serial.printf("%c",(char)buffer[i]);
    Serial.println();

}

void setup(){
 Serial.begin(115200);
 Serial.println("Začínam\n");
 GCM <AES256> *gcm=0;
 gcm= new GCM<AES256>();
 gcm->setKey(testVectorGCM.key, 32);
 gcm->setIV(testVectorGCM.iv,testVectorGCM.ivsize);
 crypto_feed_watchdog();
 memset(buffer, (int)'\0', sizeof(buffer));
 char vstup[30]="Tak to netuším";     //String containing Non-Asci characters
 for(uint8_t i=0; i<30; i++) buffer[i]=vstup[i];
 encrypt(gcm,&testVectorGCM,30);
 decrypt(gcm,&testVectorGCM,30);
 delete gcm;
}

void loop(){
 delay(1000);
 Serial.print(".");
}

```
simple key generator in PHP:
```
<?php
for($i=0;$i<31;$i++) printf("0x%X,",random_int(0,0xFF));
printf("0x%X\n",random_int(0,0xFF));
?>
```


message:
How to use this 3-pin slide-switch?

I purchased [these slide switches][1] recently because I want to use them in my project:

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

But I don't know what to connect up the three pins to and I can't find any information about them online. Nor can I find sample code. Can someone show me how to wire them up and provide sample code please? I just want to be able to check their state and save it as a boolean variable.

  [1]: https://www.amazon.com/gp/product/B007QAJUUS/
  [2]: https://i.stack.imgur.com/nq9Jz.jpg

body:
Since it has two possible positions, and three pins, you have a connection between pin 1 and 2 when position 1 is selected, and between pin 1 and 3 when position 2 is selected.
As BSF comment below, the middle pin is common. This means it will be connected to the outside pins depending on where the switch is moved towards.

However, you always can verify this, in the following way:

To find out which is pin 1, pin 2 and pin 3, use a multimeter. Set it to continuity mode, or if you don't have that mode, to resistance mode, and put the red/black probes to two random pins. Check if the resistance is 0, in that case you know those two pins will be connected when position 1 is selected. If there is resistance, try other pins with the probes, until you know which are connected.

Than switch the position, and do it again.

Instead of a multimeter you also can 'hardwire'  it to e.g. 5V -> pin 1, pin 2 -> resistor of 220 ohm -> LED -> GND
And change pin 1 and pin 2 until you found which pins connect for which positions.

To use it for you Arduino, check for a normal simple switch example, but these are two in one, one for each position.


body:
These switches are actually a lot more simple than you would think.  You have two positions, but you really only care about one of them, since if it's not in that position it must be in the other.

The central pin is the common, and when slid to one side it connects that central pin to the corresponding outside pin.

So you just use the central pin and *one* of the outside pins as if it were any other on-off switch or pushbutton.  Treat it *exactly* the same (pullup resistor, which may be internal to the AVR chip, and connect the IO pin to ground through the switch).

If it's "on" (reads LOW) then the switch is in one position. If it's "off" (reads HIGH) then it's in the other position.

The only times you'd want to use both outer pins is if you were wanting to direct a signal to one of two different places, or select between two different incoming signals, or if the switch were a "3 position on-off-on" switch where it can be in either outer position or *neither* position (centre off), in which case you treat it as two separate switches, but with a common central pin that connects both to ground.


body:
As others have said, this is a SPDT (Single Pole Double Throw) switch. The center pin is common. When the switch is slid one way, it connects the center pin to the outer pin on that side. When you slide the switch the other way, it connects the center pin to the opposite outer pin.

See the link about SPDT switches Edgar provided in his comment: http://www.learningaboutelectronics.com/Articles/What-is-a-single-pole-double-throw-switch-SPDT

That explains these switches pretty clearly.

Connect the center pin of the switch to a digital pin on your Arduino. Connect one of the outer pins to ground.

Set the digital pin on the Arduino to `INPUT_PULLUP` mode.

Then, when you read the digital state of the pin, if it is LOW, the switch is closed. (Slid to the side of the pin you attached to ground.)


message:
Parola library and DS3231 clock

EDIT2: Well, this is the "new" code and it just displays random dots on the matrices:

```
#include "RTClib.h"

#include <MD_Parola.h>
#include <MD_MAX72xx.h>
#include <SPI.h>

// Define the number of devices we have in the chain and the hardware interface
// NOTE: These pin numbers will probably not work with your hardware and may
// need to be adapted
#define HARDWARE_TYPE MD_MAX72XX::FC16_HW
#define MAX_DEVICES 16
#define NUM_ZONES 4

#define CLK_PIN   13
#define DATA_PIN  11
#define CS_PIN    10

// Hardware SPI connection
MD_Parola P = MD_Parola(HARDWARE_TYPE, CS_PIN, MAX_DEVICES);
// Arbitrary output pins
// MD_Parola P = MD_Parola(HARDWARE_TYPE, DATA_PIN, CLK_PIN, CS_PIN, MAX_DEVICES);

RTC_DS3231 rtc;
#define SPEED_TIME  25
#define PAUSE_TIME  1000

uint8_t lastUpdateMin = 0;
uint8_t lastUpdateHour = 0;

// Global variable
const char  *pc[NUM_ZONES] =
{
  "TIME",
  "ROOM", //0
  "SUBJECT", //1
  "GRADE",//2
  };

void setup(void)
{

  P.begin();
    if (! rtc.begin()) {
    Serial.println("Couldn't find RTC");
    while (1);
  }

 if (rtc.lostPower()) {
    Serial.println("RTC lost power, lets set the time!");
//     If the RTC have lost power it will set the RTC to the date & time this sketch was compiled in the following line
   rtc.adjust(DateTime(F(__DATE__), F(__TIME__)));
 }

 P.begin(4);
  P.setZone(0, 0, 3); // Modules 0-3 in zone 0
  P.setZone(1, 4, 7); // Modules 4-7 in zone 1
  P.setZone(2, 8, 11); // Modules 8-11 in zone 2
  P.setZone(3, 12, 15); // Modules 12-15 in zone 3
}

void loop(void)
{

 DateTime now = rtc.now();
 if(lastUpdateMin != now.minute()){  // change every minute
     lastUpdateMin = now.minute();
 char buffer[] = "hh:mm";  // hours and minutes
P.displayZoneText(0,now.toString(buffer), PA_CENTER, 0, 0, PA_PRINT, PA_NO_EFFECT);

    if(lastUpdateHour != now.hour()){     // change every hour
     lastUpdateHour = now.hour();
   P.displayZoneText(1, pc[1], PA_RIGHT, 0, 0, PA_PRINT, PA_NO_EFFECT);
   P.displayZoneText(2, pc[2], PA_LEFT, 0, 0, PA_PRINT, PA_NO_EFFECT);  // display
   P.displayZoneText(3, pc[3], PA_CENTER, 0, 0, PA_PRINT, PA_NO_EFFECT);
   }
  }
   P.displayAnimate();
}

```
If I do just this:
```
void loop(void)
{

 DateTime now = rtc.now();
 if(lastUpdateMin != now.minute()){  // change every minute
     lastUpdateMin = now.minute();
 char buffer[] = "hh:mm";  // hours and minutes
P.displayZoneText(0,now.toString(buffer), PA_CENTER, 0, 0, PA_PRINT, PA_NO_EFFECT);
 }
     if(lastUpdateHour != now.hour()){     // change every hour
     lastUpdateHour = now.hour();

     }

   P.displayAnimate();
}
```
it displays the hour:minutes.
the problem is it doesn't display the time and the other text at the same time

EDIT: If I execute this code below it will display text on the first row, but my question will be how do I manage to display simultaneously the hour:minutes from the clock and some text of my choice?
```
void setup(void)
{

  P.begin();
    if (! rtc.begin()) {
    Serial.println("Couldn't find RTC");
    while (1);
  }

 if (rtc.lostPower()) {
    Serial.println("RTC lost power, lets set the time!");
//     If the RTC have lost power it will set the RTC to the date & time this sketch was compiled in the following line
   rtc.adjust(DateTime(F(__DATE__), F(__TIME__)));
 }

 P.begin(4);
  P.setZone(0, 0, 3); // Modules 0-3 in zone 0
  P.setZone(1, 4, 7); // Modules 4-7 in zone 1
  P.setZone(2, 8, 11); // Modules 8-11 in zone 2
  P.setZone(3, 12, 15); // Modules 12-15 in zone 3

for (uint8_t i=0; i<NUM_ZONES; i++)
    P.displayZoneText(0, pc[0], PA_CENTER, 0, 0, PA_PRINT, PA_NO_EFFECT);

}

void loop(void)
{

 DateTime now = rtc.now();
 char buffer[] = "hh:mm";  // hours and minutes

// P.displayZoneText(0,now.toString(buffer), PA_CENTER, 0, 0, PA_PRINT, PA_NO_EFFECT);  // display
//if(now.hour()==12){
//  P.displayZoneText(0, pc[0], PA_CENTER, 0, 0, PA_PRINT, PA_NO_EFFECT);
//}
//else{
 // P.displayZoneText(1, pc[1], PA_CENTER, 0, 0, PA_PRINT, PA_NO_EFFECT);  // display
//}
   P.displayAnimate();
}
```

I have multiple FC-16 modules based on MAX7219 led matrices and I want to use them and a real time clock, DS3231, to build a classroom timetable.

I want the led modules to operate on the concept of zones. I want to create a zone for each row of text (a zone is a contiguous block of modules forming a kind of sub-display) as I did here: ```P.begin(4); // We will have 4 zones
P.setZone(0, 0, 3); // Modules 0-3 in zone 0
P.setZone(1, 4, 7); // Modules 4-7 in zone 1
P.setZone(2, 8, 11); // Modules 8-11 in zone 2
P.setZone(3, 12, 15); // Modules 12-15 in zone 3```

I want this in order to be able to change the text in a row without modifying other rows.

Then, I need to use the hour and minutes from the DS3231 clock module and to display it on the first row of the display and on the other 3 rows I need to display the number of the room, the subject and the class.
```uint8_t  curText;
const char  *pc[NUM_ZONES] =
{
  "ROOM",
  "SUBJECT",
  "CLASS",};
 ```
And when the hour on the first row changes, the text from the other 3 rows should change simultaneously.It's a pretty simple concept but I can't seem to know how to manage this.
This is all the code I gathered up until now:

```
#include "RTClib.h"

#include <MD_Parola.h>
#include <MD_MAX72xx.h>
#include <SPI.h>

// Define the number of devices we have in the chain and the hardware interface
// NOTE: These pin numbers will probably not work with your hardware and may
// need to be adapted
#define HARDWARE_TYPE MD_MAX72XX::FC16_HW
#define MAX_DEVICES 16
#define NUM_ZONES 4

#define CLK_PIN   13
#define DATA_PIN  11
#define CS_PIN    10

// Hardware SPI connection
MD_Parola P = MD_Parola(HARDWARE_TYPE, CS_PIN, MAX_DEVICES);
// Arbitrary output pins
// MD_Parola P = MD_Parola(HARDWARE_TYPE, DATA_PIN, CLK_PIN, CS_PIN, MAX_DEVICES);
RTC_DS3231 rtc;
#define SPEED_TIME  25
#define PAUSE_TIME  1000

// Global variables
uint8_t  curText;
const char  *pc[NUM_ZONES] =
{
  "ROOM",
  "SUBJECT",
  "CLASS",

};

void setup(void)
{

  P.begin();
    if (! rtc.begin()) {
    Serial.println("Couldn't find RTC");
    while (1);
  }

 if (rtc.lostPower()) {
    Serial.println("RTC lost power, lets set the time!");
//     If the RTC have lost power it will set the RTC to the date & time this sketch was compiled in the following line
   rtc.adjust(DateTime(F(__DATE__), F(__TIME__)));
 }

 P.begin(4);
  P.setZone(0, 0, 3); // Modules 0-3 in zone 0
  P.setZone(1, 4, 7); // Modules 4-7 in zone 1
  P.setZone(2, 8, 11); // Modules 8-11 in zone 2
  P.setZone(3, 12, 15); // Modules 12-15 in zone 3

}

void loop(void)
{

 DateTime now = rtc.now();
 char buffer[] = "hh:mm";  // hours and minutes

   for (uint8_t i=0; i<NUM_ZONES; i++)
    P.displayZoneText(i-1, now.toString(buffer), PA_CENTER, 0, 0, PA_PRINT, PA_NO_EFFECT);

P.displayAnimate();
}
```

I dont't know how to display the hour:minutes and my text simultaneously so that I can do the rest then:
```void loop(void)
{

 DateTime now = rtc.now();
 char buffer[] = "hh:mm";  // hours and minutes

   for (uint8_t i=0; i<NUM_ZONES; i++)
    P.displayZoneText(i-3, now.toString(buffer), PA_CENTER, 0, 0, PA_PRINT, PA_NO_EFFECT); //here I want to display the hour:minutes on the first row

P.displayAnimate();
}```

body:
Your first problem is the definition of the text array:

    const char  *pc[NUM_ZONES] =
    { "TIME",      // This will be replaced by real time its only for logic of rows here
      "ROOM",
      "SUBJECT",
      "CLASS"
    };

then we need a timer, as you only show minutes we only have to change time in that interval to prevent flicker and other unwanted effects and hour for changing texts lateron:

    uint8_t lastUpdateMin = 0;
    uint8_t lastUpdateHour = 0;

Then the loop looks like

    void loop() {
       DateTime now = rtc.now();
       if(lastUpdateMin != now.minute()){  // change every minute
         lastUpdateMin = now.minute();
         char buffer[] = "hh:mm";  // hours and minutes
         P.displayZoneText(0, now.toString(buffer), PA_CENTER, 0, 0, PA_PRINT, PA_NO_EFFECT); // 1st row
        }
      if(lastUpdateHour != now.hour()){     // change every hour
         lastUpdateHour = now.hour();
         P.displayZoneText(1, pc[1], PA_RIGHT, 0, 0, PA_PRINT, PA_NO_EFFECT);  // 2nd row
         P.displayZoneText(2, pc[2], PA_LEFT, 0, 0, PA_PRINT, PA_NO_EFFECT);   // 3rd row
         P.displayZoneText(3, pc[3], PA_CENTER, 0, 0, PA_PRINT, PA_NO_EFFECT); // 4th row
        }
    P.displayAnimate();
    }

Things to do - define a two dimensional char table with all the texts needed for the different hours

    #define NUM_LECTUREHOURS 7       // seven hour lectures
    const char *pc[NUM_LECTUREHOURS][NUM_ZONES] = {
      { "TIME", "ROOM_0", "SUBJECT_0", "CLASS_0"},
      { "TIME", "ROOM_1", "SUBJECT_1", "CLASS_1"},
      { "TIME", "ROOM_2", "SUBJECT_2", "CLASS_2"},
      ...
      { "TIME", "ROOM_Last", "SUBJECT_Last", "CLASS_Last"}  // _Last in this example = 6
    };

and display with a variable based on the hour so if your classes start at 9:00 you would use

    uint8_t lectureHour= now.hour() - 9; // as arrays start with 0

and your different texts would be called like

      P.displayZoneText(1, pc[lectureHour][1], PA_RIGHT, 0, 0, PA_PRINT, PA_NO_EFFECT); // 2nd row

If your char array gets to large - depending on the texts - you will have to use PROGMEM which is an issue on its own. Hope this gets you started

**EDIT**
If you want to change every two hours you do

  if(lastUpdateHour != now.hour() && lastUpdateHour +1 != now.hour() ){     // change every two hours

or shorter for a variable timespan (e.g. every three hours)

     if( now.hour() - lastUpdateHour > 3 ){     // change every three hours


message:
LSM303 unable to compensate tilt

I am working on a tilt compensated compass with the LSM303DLHC. I manage to calibrate the magnetic and accelero part. I managed to calculate pitch and roll. But when it comes to calculate tilt compensation for the compass something goes wrong. My values on the serial monitor just don't make sense...If I calculate compass heading from calibrated magneto values it works using the Y axis as the magnetic vector. How would I be able to change that to the X-axis?
```/*This program is reading out a magnetometer sensor
   LSM303DLHC including accelerometer to correct for position

*/
#include <Wire.h>

const int LSM303_ADDR = 0x19;
const int LSM303_ADDR_MAG = 0x1E;

//control register addresses
const int CTRL_REG1_ADDR = 0x20;
const int CTRL_REG2_ADDR = 0x21;
const int CTRL_REG3_ADDR = 0x22;
const int CTRL_REG4_ADDR = 0x23;
const int CTRL_REG5_ADDR = 0x24;
const int CTRL_REG6_ADDR = 0x25;

const int CRA_REG_M_ADDR = 0x00;
const int CRB_REG_M_ADDR = 0x01;
const int MR_REG_M_ADDR = 0x02;

//data register addresses LSB first for accelero, MSB first for magneto
const int Accelero_First_data_addr = 0x28;
const int Magneto_First_data_addr = 0x03;
const int Temp_out_data_addr = 0x31;//MSB first 12 bits

int CTRL_REG1_A_value = 0x47; //50Hz Low Power disable, all axes enabled
int CTRL_REG2_A_value = 0x00; //
int CTRL_REG3_A_value = 0x00; //no interrupt or watermark enabled
int CTRL_REG4_A_value = 0x00; // 2G full scale, high resolution, no SPI mode selected
int CTRL_REG5_A_value = 0x00; // nothing enabled
int CTRL_REG6_A_value = 0x00; // nothing enabled

int CRA_REG_M_value = 0x14; // Temp sens enabled, 15Hz data rate output
int CRB_REG_M_value = 0x20; // 2G is data 1100 - 980 G/LSB

int MR_REG_M_value = 0x00;

int16_t MagRaw_X_axis_value, MagRaw_Y_axis_value, MagRaw_Z_axis_value;
int16_t AccRaw_X_axis_value, AccRaw_Y_axis_value, AccRaw_Z_axis_value;

float pitch, roll;
float Xm_calibrated, Ym_calibrated, Zm_calibrated;
float Xm_norm, Ym_norm, Zm_norm, Xa_norm, Ya_norm, Za_norm;
float norm_a, norm_m;

void setup() {// put your setup code here, to run once:
  Serial.begin(9600);
  Wire.begin();
  setupLSM303();
  Serial.println("Setup complete..");
}

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

}

void setupLSM303() {
  Wire.beginTransmission(LSM303_ADDR);
  Wire.write(CTRL_REG1_ADDR);
  Wire.write(CTRL_REG1_A_value);
  Wire.endTransmission();
  Wire.beginTransmission(LSM303_ADDR);
  Wire.write(CTRL_REG2_ADDR);
  Wire.write(CTRL_REG2_A_value);
  Wire.endTransmission();
  Wire.beginTransmission(LSM303_ADDR);
  Wire.write(CTRL_REG3_ADDR);
  Wire.write(CTRL_REG3_A_value);
  Wire.endTransmission();
  Wire.beginTransmission(LSM303_ADDR);
  Wire.write(CTRL_REG4_ADDR);
  Wire.write(CTRL_REG4_A_value);
  Wire.endTransmission();
  Wire.beginTransmission(LSM303_ADDR);
  Wire.write(CTRL_REG5_ADDR);
  Wire.write(CTRL_REG5_A_value);
  Wire.endTransmission();
  Wire.beginTransmission(LSM303_ADDR);
  Wire.write(CTRL_REG6_ADDR);
  Wire.write(CTRL_REG6_A_value);
  Wire.endTransmission();
  //magneto register setup
  Wire.beginTransmission(LSM303_ADDR_MAG);
  Wire.write(CRA_REG_M_ADDR);
  Wire.write(CRA_REG_M_value);
  Wire.endTransmission();
  Wire.beginTransmission(LSM303_ADDR_MAG);
  Wire.write(CRB_REG_M_ADDR);
  Wire.write(CRB_REG_M_value);
  Wire.endTransmission();
  Wire.beginTransmission(LSM303_ADDR_MAG);
  Wire.write(MR_REG_M_ADDR);
  Wire.write(MR_REG_M_value);
  Wire.endTransmission();
}

void MagnetoDataRead() {
  Wire.beginTransmission(LSM303_ADDR_MAG );
  Wire.write(Magneto_First_data_addr);
  Wire.endTransmission();

  Wire.requestFrom(LSM303_ADDR_MAG , 6);
  if (Wire.available() <= 6) {
    MagRaw_X_axis_value = (Wire.read() << 8) | (Wire.read());
    MagRaw_Y_axis_value = (Wire.read() << 8) | (Wire.read());
    MagRaw_Z_axis_value = (Wire.read() << 8) | (Wire.read());

    float X_mag_cal = MagRaw_X_axis_value / 1100.0;
    float Y_mag_cal = MagRaw_Y_axis_value / 1100.0;
    float Z_mag_cal = MagRaw_Z_axis_value / 980.0;

    //input calibration factors
    float Xm_offset_corrected = MagRaw_X_axis_value - 0.041423;
    float Ym_offset_corrected = MagRaw_Y_axis_value + 0.022448;
    float Zm_offset_corrected = MagRaw_Z_axis_value + 0.078354;

    Xm_calibrated = 94.622065 * Xm_offset_corrected + 0.831029 * Ym_offset_corrected + 1.647934 * Zm_offset_corrected;
    Ym_calibrated = 0.831029 * Xm_offset_corrected + 93.462985 * Ym_offset_corrected + 3.416885 * Zm_offset_corrected;
    Zm_calibrated = 1.647934 * Xm_offset_corrected + 3.416885 * Ym_offset_corrected + 76.477691 * Zm_offset_corrected;

    //normalization formula
    norm_m = sqrt(sq(Xm_calibrated) + sq(Ym_calibrated) + sq(Zm_calibrated));
    Xm_norm = Xm_calibrated / norm_m;
    Ym_norm = Ym_calibrated / norm_m;
    Zm_norm = Zm_calibrated / norm_m;

    //float Heading = ((atan2(Ym_calibrated, Xm_calibrated)) * 180 ) / PI;
    //if (Heading < 0) {
    //  Heading = 360 + Heading;
    //}
    /*
        Serial.print(X_mag_cal, 10);
        Serial.print("\t");
        Serial.print(Y_mag_cal, 10);
        Serial.print("\t");
        Serial.print(Z_mag_cal, 10);
        Serial.println("\t");
    */

    delay(50);

  }
}

void AcceleroDataRead() {
  Wire.beginTransmission(LSM303_ADDR);
  Wire.write(Accelero_First_data_addr | 0x80);
  Wire.endTransmission();

  Wire.requestFrom(LSM303_ADDR, 6);
  if (Wire.available() <= 6) {
    AccRaw_X_axis_value = (Wire.read()) | (Wire.read() << 8);
    AccRaw_Y_axis_value = (Wire.read()) | (Wire.read() << 8);
    AccRaw_Z_axis_value = (Wire.read()) | (Wire.read() << 8);

    float X_Acc =  (AccRaw_X_axis_value >> 4);
    float Y_Acc =  (AccRaw_Y_axis_value >> 4);
    float Z_Acc =  (AccRaw_Z_axis_value >> 4);
//calibrate offset
    float X_acc_offset_corrected = X_Acc + 6.676443;
    float Y_acc_offset_corrected = Y_Acc - 6.622381;
    float Z_acc_offset_corrected = Z_Acc + 55.408804;
//calibrate
    float X_acc_calibrated = 0.977273 * X_acc_offset_corrected - 0.003458 * Y_acc_offset_corrected + 0.012639 * Z_acc_offset_corrected;
    float Y_acc_calibrated = -0.003458 * X_acc_offset_corrected + 0.979674 * Y_acc_offset_corrected - 0.001130 * Z_acc_offset_corrected;
    float Z_acc_calibrated = 0.012639 * X_acc_offset_corrected - 0.001130 * Y_acc_offset_corrected + 0.897083 * Z_acc_offset_corrected;
//normalize
    norm_a = sqrt(sq(X_acc_calibrated) + sq(Y_acc_calibrated) + sq(Z_acc_calibrated));
    Xa_norm = X_acc_calibrated / norm_a;
    Ya_norm = Y_acc_calibrated / norm_a;
    Za_norm = Z_acc_calibrated / norm_a;

//calculate pitch and roll
    pitch = asin(-Xa_norm) * 180 / PI;
    roll = (atan2(Ya_norm, Za_norm) * 180) / PI;
//calculate vectors fo tilt compensation
    float Xh = Xm_norm * cos(pitch * PI / 180) + Zm_norm * sin(pitch * PI / 180);
    float Yh = Xm_norm * sin(roll * PI / 180) * sin(pitch * PI / 180) + Ym_norm * cos(roll * PI / 180) - Zm_norm * sin(roll * PI / 180) * cos(pitch * PI / 180);
//calculate tilt compensated heading
    float Heading = ((atan2(Yh, Xh)) * 180.0 ) / PI;
    if (Heading < 0) {
      Heading = 360 + Heading;
    }

    Serial.print("Pitch \t");
    Serial.print(pitch);
    Serial.print("\t roll \t");
    Serial.print(roll);
    Serial.print("\t");
    Serial.println(Heading);

    delay(50);
  }
}
 ```
I have been stuck on this for a few days now. Any help is appreciated!

body: Found it...Magneto data is coming out XZY not XYZ...when I changed this it works! Sorry, RTFMA would have given me the answer straight away.


body:
It seems I got it working! Thanks a lot for your help, I owe you a few beers. For anyone following and interested here is my code:
```/*This program is reading out a magnetometer sensor
   LSM303DLHC including accelerometer to correct for position
  Vector calculation to be implemented
*/
#include <Wire.h>
#include <Math.h>

const int LSM303_ADDR = 0x19;
const int LSM303_ADDR_MAG = 0x1E;

//control register addresses
const int CTRL_REG1_ADDR = 0x20;
const int CTRL_REG2_ADDR = 0x21;
const int CTRL_REG3_ADDR = 0x22;
const int CTRL_REG4_ADDR = 0x23;
const int CTRL_REG5_ADDR = 0x24;
const int CTRL_REG6_ADDR = 0x25;

const int CRA_REG_M_ADDR = 0x00;
const int CRB_REG_M_ADDR = 0x01;
const int MR_REG_M_ADDR = 0x02;

//data register addresses LSB first for accelero, MSB first for magneto
const int Accelero_First_data_addr = 0x28;
const int Magneto_First_data_addr = 0x03;
const int Temp_out_data_addr = 0x31;//MSB first 12 bits

int CTRL_REG1_A_value = 0x47; //50Hz Low Power disable, all axes enabled
int CTRL_REG2_A_value = 0x00; //
int CTRL_REG3_A_value = 0x00; //no interrupt or watermark enabled
int CTRL_REG4_A_value = 0x00; // 2G full scale, high resolution, no SPI mode selected
int CTRL_REG5_A_value = 0x00; // nothing enabled
int CTRL_REG6_A_value = 0x00; // nothing enabled

int CRA_REG_M_value = 0x14; // Temp sens enabled, 15Hz data rate output
int CRB_REG_M_value = 0x20; // 2G is data 1100 - 980 G/LSB

int MR_REG_M_value = 0x00;

int16_t MagRaw_X_axis_value, MagRaw_Y_axis_value, MagRaw_Z_axis_value;
int16_t AccRaw_X_axis_value, AccRaw_Y_axis_value, AccRaw_Z_axis_value;

float pitch, roll;
float Xm_calibrated, Ym_calibrated, Zm_calibrated;
float Xm_norm, Ym_norm, Zm_norm, Xa_norm, Ya_norm, Za_norm;
float norm_a, norm_m;

void setup() {// put your setup code here, to run once:
  Serial.begin(9600);
  Wire.begin();
  setupLSM303();
  Serial.println("Setup complete..");
}

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

}

void setupLSM303() {
  Wire.beginTransmission(LSM303_ADDR);
  Wire.write(CTRL_REG1_ADDR);
  Wire.write(CTRL_REG1_A_value);
  Wire.endTransmission();
  Wire.beginTransmission(LSM303_ADDR);
  Wire.write(CTRL_REG2_ADDR);
  Wire.write(CTRL_REG2_A_value);
  Wire.endTransmission();
  Wire.beginTransmission(LSM303_ADDR);
  Wire.write(CTRL_REG3_ADDR);
  Wire.write(CTRL_REG3_A_value);
  Wire.endTransmission();
  Wire.beginTransmission(LSM303_ADDR);
  Wire.write(CTRL_REG4_ADDR);
  Wire.write(CTRL_REG4_A_value);
  Wire.endTransmission();
  Wire.beginTransmission(LSM303_ADDR);
  Wire.write(CTRL_REG5_ADDR);
  Wire.write(CTRL_REG5_A_value);
  Wire.endTransmission();
  Wire.beginTransmission(LSM303_ADDR);
  Wire.write(CTRL_REG6_ADDR);
  Wire.write(CTRL_REG6_A_value);
  Wire.endTransmission();
  //magneto register setup
  Wire.beginTransmission(LSM303_ADDR_MAG);
  Wire.write(CRA_REG_M_ADDR);
  Wire.write(CRA_REG_M_value);
  Wire.endTransmission();
  Wire.beginTransmission(LSM303_ADDR_MAG);
  Wire.write(CRB_REG_M_ADDR);
  Wire.write(CRB_REG_M_value);
  Wire.endTransmission();
  Wire.beginTransmission(LSM303_ADDR_MAG);
  Wire.write(MR_REG_M_ADDR);
  Wire.write(MR_REG_M_value);
  Wire.endTransmission();
}

void MagnetoDataRead() {
  Wire.beginTransmission(LSM303_ADDR_MAG );
  Wire.write(Magneto_First_data_addr);
  Wire.endTransmission();

  Wire.requestFrom(LSM303_ADDR_MAG , 6);
  if (Wire.available() <= 6) {
    MagRaw_X_axis_value = (Wire.read() << 8) | (Wire.read());
    MagRaw_Z_axis_value = (Wire.read() << 8) | (Wire.read());
    MagRaw_Y_axis_value = (Wire.read() << 8) | (Wire.read());

    float X_mag_cal = MagRaw_X_axis_value / 1100.0;
    float Y_mag_cal = MagRaw_Y_axis_value / 1100.0;
    float Z_mag_cal = MagRaw_Z_axis_value / 980.0;

    //input calibration factors
    float Xm_offset_corrected = X_mag_cal - 0.032874;
    float Ym_offset_corrected = Y_mag_cal + 0.047876;
    float Zm_offset_corrected = Z_mag_cal + 0.039649;

    Xm_calibrated = 92.387197 * Xm_offset_corrected - 0.307374 * Ym_offset_corrected + 1.151625 * Zm_offset_corrected;
    Ym_calibrated = -0.307374 * Xm_offset_corrected + 85.002110 * Ym_offset_corrected + 1.169755 * Zm_offset_corrected;
    Zm_calibrated = 1.151625 * Xm_offset_corrected + 1.169755 * Ym_offset_corrected + 80.276037 * Zm_offset_corrected;

    //normalization formula
    norm_m = sqrt(sq(Xm_calibrated) + sq(Ym_calibrated) + sq(Zm_calibrated));
    Xm_norm = Xm_calibrated / norm_m;
    Ym_norm = Ym_calibrated / norm_m;
    Zm_norm = Zm_calibrated / norm_m;

    /*
        Serial.print(X_mag_cal, 10);
        Serial.print("\t");
        Serial.print(Y_mag_cal, 10);
        Serial.print("\t");
        Serial.print(Z_mag_cal, 10);
        Serial.println("\t");
    */

    //float Heading = ((atan2(Ym_norm, Xm_norm)) * 180.0 ) / PI;
    //if (Heading < 0) {
    // Heading = 360 + Heading;
    //}
    //Serial.println(Heading);
    //delay(50);

  }
}

void AcceleroDataRead() {
  Wire.beginTransmission(LSM303_ADDR);
  Wire.write(Accelero_First_data_addr | 0x80);
  Wire.endTransmission();

  Wire.requestFrom(LSM303_ADDR, 6);
  if (Wire.available() <= 6) {
    AccRaw_X_axis_value = (Wire.read()) | (Wire.read() << 8);
    AccRaw_Y_axis_value = (Wire.read()) | (Wire.read() << 8);
    AccRaw_Z_axis_value = (Wire.read()) | (Wire.read() << 8);

    float X_Acc =  (AccRaw_X_axis_value >> 4);
    float Y_Acc =  (AccRaw_Y_axis_value >> 4);
    float Z_Acc =  (AccRaw_Z_axis_value >> 4);

    //calibrate offset
    float X_acc_offset_corrected = X_Acc + 6.676443;
    float Y_acc_offset_corrected = Y_Acc - 6.622381;
    float Z_acc_offset_corrected = Z_Acc + 55.408804;

    //calibrate
    float X_acc_calibrated = 0.977273 * X_acc_offset_corrected - 0.003458 * Y_acc_offset_corrected + 0.012639 * Z_acc_offset_corrected;
    float Y_acc_calibrated = -0.003458 * X_acc_offset_corrected + 0.979674 * Y_acc_offset_corrected - 0.001130 * Z_acc_offset_corrected;
    float Z_acc_calibrated = 0.012639 * X_acc_offset_corrected - 0.001130 * Y_acc_offset_corrected + 0.897083 * Z_acc_offset_corrected;
    //normalize
    norm_a = sqrt(sq(X_acc_calibrated) + sq(Y_acc_calibrated) + sq(Z_acc_calibrated));
    Xa_norm = X_acc_calibrated / norm_a;
    Ya_norm = Y_acc_calibrated / norm_a;
    Za_norm = Z_acc_calibrated / norm_a;

    //calculate pitch and roll
    /*
      pitch = asin(-Xa_norm) * 180 / PI;
      roll = asin(Ya_norm / cos(pitch * PI / 180)) * 180 / PI;
    */
    roll = atan2(Ya_norm, Za_norm);
    float  Gz2 = Ya_norm * sin(roll) + Za_norm * cos(roll);
    pitch = atan(-Xa_norm / Gz2);
    float By2 = Zm_norm * sin(roll) - Ym_norm * cos(roll);
    float Bz2 = Ym_norm * sin(roll) + Zm_norm * cos(roll);
    float Bx3 = Xm_norm * cos(pitch) + Bz2 * sin(pitch);
    float yaw = (atan2(By2, Bx3)*180)/PI;
    if (yaw < 0) {
      yaw = 360 + yaw;
    }

    float tilt = atan2(sqrt((sq(Xa_norm)+(sq(Ya_norm)))),Za_norm);

    //calculate vectors fo tilt compensation
    float Xh = Xm_norm * cos(pitch) + Zm_norm * sin(pitch);
    float Yh = Xm_norm * sin(roll ) * sin(pitch) + Ym_norm * cos(roll) - Zm_norm * sin(roll) * cos(pitch);

        // calculate tilt compensated heading
        float Heading = ((atan2(Yh, Xh)) * 180.0 ) / PI;
        if (Heading < 0) {
          Heading = 360 + Heading;
        }

    Serial.print("Pitch \t");
    Serial.print(pitch * 180 / PI);
    Serial.print("\t roll \t");
    Serial.print(roll * 180 / PI);
    Serial.print("\t tilt \t");
    Serial.print(tilt*180/PI);
    Serial.print("\t");
    Serial.println(Heading);
    delay(500);
  }
}
```