body:
Mega 2560.
I can't get the RFID board detected. The code is below, and outputs "Didn't find MFRC522 board.". I also tested some other library and test code with success.

I triple checked the wires (3,3V pin, gnd, and PWM pin 8 and 9).

I have some questions:

1. All tutorials shows that MOSI, MISO, SCK needs to be hooked up to digital pin 50, 51, 52. But I don't understand why these matter, because they are not referenced in any code I've found? Are they really necessary? And if so, does it have to be 50,51,52? Can't it be any other digital pin?

2. I accidentally connected it to 5V at first, for maybe 1 minute. Could it be burnt? The LED still lights RED when connected with power.

3. If the problem was the (correct) library was not loaded, wouldn't I get a compile error?

I'm running this code:

    #include <MFRC522.h>
    #include <SPI.h>

    #define SAD 9
    #define RST 8

    MFRC522 nfc(SAD, RST);

    void setup() {
      SPI.begin();
      Serial.begin(115200);

      Serial.println("Looking for MFRC522.");
      nfc.begin();

      uint8_t version = nfc.getFirmwareVersion();
      if (! version) {
        Serial.print("Didn't find MFRC522 board.");
        while(1); //halt
      }

      Serial.print("Found chip MFRC522 ");
      Serial.print("Firmware ver. 0x");
      Serial.print(version, HEX);
      Serial.println(".");

      if (nfc.digitalSelfTestPass()) {
          Serial.print("Digital self test by MFRC522 passed.");
      } else {
          Serial.print("Digital self test by MFRC522 failed.");
      }
    }

    void loop() {

    }

title: MFRC522 board not detected. Red LED lighting

Answers: 1

body:
Welcome, hopefully we can help you. You do not have to connect MOSI, MISO, SCK, CS if you do not want to however without them connected properly it will not work. Note you did not mention the CS pin, that is also needed as that is what tells the MFRC522 it has been selected. Those pins are what is used to communicate with the device. The pins may be different for different boards but you need to check the data sheet for that. The numbers appear correct for the Mega.

The LED tells you that there is power there, it in no way tells you if the board is good. Did you fry it, probably probably as the MFRC522 is a 3V3 device but that is not a given as I do not know what pin you connected the 5V to. More than a few nanoseconds on a voltage higher than rated tends to fry things, but you could be lucky I have no way of knowing. The Mega is 5V so that would probably be OK.

You ask: "If the problem was the (correct) library was not loaded, wouldn't I get a compile error?", again no not necessarily. The compiler does not know your design or what you are connecting to. If the library happens to have functions etc appropriately named it will compile with errors but the odds are very slim your code will work.


body:
I'm using a teensy 4.0 with two mcp23s17 gpio expanders where #1 has 16 buttons wired to it, and #2 has 4 buttons and six rotary encoders. To run everything I'm using majenkos mcp23s17 library. Recently, I refactored my code, and suddenly I'm unable to setup the mcp's to have interrupts working properly.

I've tried to narrow the problem down by commenting out code, and it appears that as soon as I call         ```gpioExpander.enableInterrupt(pin, CHANGE);``` in ```gpioSetup()``` the problem occurs. In detail, ```loop()``` runs fine, but as soon as I press a button, the teensy hangs. Also, to restore the teensy I have to upload the code with the call to ```gpioExpander.enableInterrupt(pin, CHANGE);``` commented out in order to have the teensy up and running again.

I've been staring myself blind on the code, and I suspect I'm missing something obvious. Your help is appreciated.

```c++ [code]
//main.cpp
#include <Arduino.h>

#include "GPIO.h"
#include "MCP23S17.h"

extern MCP23S17 gpioExpander1;
extern MCP23S17 gpioExpander2;

void setup() {
    Serial.begin(115200);
    gpioSetup();
}

void loop() {
    GPIOtest(gpioExpander1, gpioExpander2);
}

//GPIO.h
#ifndef GPIO_H
#define GPIO_H

#include <Arduino.h>

#include "MCP23S17.h"

constexpr uint8_t address = 0;
constexpr uint8_t interruptPin1 = 8;
constexpr uint8_t interruptPin2 = 22;
constexpr uint8_t chipSelectPin1 = 7;
constexpr uint8_t chipSelectPin2 = 21;

void setGPIO1Pins(MCP23S17 &gpioExpander);
void setGPIO2Pins(MCP23S17 &gpioExpander);
void gpioSetup();
void GPIO1interrupt();
void GPIO2interrupt();
void GPIOtest(MCP23S17 &gpioExpander1, MCP23S17 &gpioExpander2);

#endif

//GPIO.cpp
#include "GPIO.h"

#include <Arduino.h>
#include <MCP23S17.h>

volatile bool interruptFlag1 = false;
volatile bool interruptFlag2 = false;

MCP23S17 gpioExpander1(&SPI, chipSelectPin1, address);
MCP23S17 gpioExpander2(&SPI, chipSelectPin2, address);

//  Set all Port Expander pins to desired mode INPUT_PULLUP
//  Set all Port Expander input pins interrupts
void setGPIOPins(MCP23S17& gpioExpander) {
    for (uint8_t pin = 0; pin <= 15; ++pin) {
        gpioExpander.pinMode(pin, INPUT_PULLUP);
        gpioExpander.enableInterrupt(pin, CHANGE);
    }

    // set Port Expander Interrupt configuratons
    gpioExpander.setMirror(true);
    gpioExpander.setInterruptOD(false);
    gpioExpander.setInterruptLevel(LOW);
}

void gpioSetup() {
    gpioExpander1.begin();
    gpioExpander2.begin();
    digitalWrite(chipSelectPin1, HIGH);
    digitalWrite(chipSelectPin2, HIGH);

    pinMode(interruptPin1, INPUT_PULLUP);
    pinMode(interruptPin2, INPUT_PULLUP);

    attachInterrupt(digitalPinToInterrupt(interruptPin1), GPIO1interrupt, LOW);
    attachInterrupt(digitalPinToInterrupt(interruptPin2), GPIO2interrupt, LOW);

    setGPIOPins(gpioExpander1);
    setGPIOPins(gpioExpander2);

    // GPIO registers are read to be cleared
    gpioExpander1.getInterruptValue();
    gpioExpander2.getInterruptValue();
}

void GPIO1interrupt() {
    interruptFlag1 = true;
}

void GPIO2interrupt() {
    interruptFlag2 = true;
}

void GPIOtest(MCP23S17& gpioExpander1, MCP23S17& gpioExpander2) {
    if (interruptFlag1 == true) {
        Serial.println("interrupt 1 = true");
        interruptFlag1 = false;
    }

    if (interruptFlag2 == true) {
        Serial.println("interrupt 2 = true");
        interruptFlag2 = false;
    }
}
```

title: Why doesn't my mcp23s17 interrupts work anymore?

Answers: 1

body:
### Short version, try:

```c++
attachInterrupt(digitalPinToInterrupt(interruptPin1), GPIO1interrupt, FALLING);
attachInterrupt(digitalPinToInterrupt(interruptPin2), GPIO2interrupt, FALLING);
```

**`FALLING`** (instead of `LOW`) being the [active ingredient][1]. I'm assuming `FALLING` is supported. If not you can try synthesizing this with `CHANGE` and reading the port to see whether or not it is currently `LOW`.

And then call `.getInterruptValue();` to clear the MCP23S17's interrupt condition where you clear the global volatile flags:

```c++
void GPIOtest(MCP23S17& gpioExpander1, MCP23S17& gpioExpander2) {
    if (interruptFlag1 == true) {
        Serial.println("interrupt 1 = true");
        interruptFlag1 = false;
        gpioExpander1.getInterruptValue(); // <------
    }

    if (interruptFlag2 == true) {
        Serial.println("interrupt 2 = true");
        interruptFlag2 = false;
        gpioExpander2.getInterruptValue(); // <------
    }
}
```

---

### Long version:

This a guess, since I'm unable to test. But this is maybe not a bad guess:

You have configured the MCP23S17 device to **drive** active **low** on/during an MCP23S17 interrupt condition:
```c++
    gpioExpander.setMirror(true);
    gpioExpander.setInterruptOD(false);
    gpioExpander.setInterruptLevel(LOW);
```

So, were an MCP23S17 interrupt to occur (`gpioExpander.enableInterrupt(pin, CHANGE);`), the interrupt flag within the MCP23S17 would be set, and INTA/INTB of the MCP23S17 would become active low.

The MCP23S17 datasheet says:

> The interrupt condition is cleared after the LSb of the data is
> clocked out during a read command of GPIO or INTCAP

You have configured your interrupt pins for interrupting on a LOW **level** interrupt:
```c++
attachInterrupt(digitalPinToInterrupt(interruptPin1), GPIO1interrupt, LOW);
```

So, if I understand this correctly, your Teensy continually re-enter the `GPIO#interrupt()` functions until something read causes the interrupt condition to be cleared. You are not clearing the interrupt condition **inside** the ISR, you're setting a flag to do that later in the main line of execution, which is reasonable by itself. One thing I can guess is that had you'd previous had something to clear the interrupt condition **inside** the interrupt and it is now outside the interrupt, namely your call to `.getInterruptValue()`, which [reads the INTCAP register][2] mentioned above. Or perhaps you'd be using [one of the functions][3] that reads a pin/port that would have cleared the interrupt condition. Clearing the global variable alone will not clear the interrupt condition, and so you're going to go right back into ISR which will reassign the global variable.

An AVR will execute a single instruction outside of the ISR before reentering the ISR. So the effect of remaining in the interrupt condition is to make your code slow, potentially **very** slow. I don't know off the top of my head what the Teensy 4.x core will do in this case. Either way, it _would_ lock up or possibly _look_ locked up.

*If* you were reading/getting-interrupt-value inside the ISR it would have cleared it and so it would not re-entered the ISR repeatedly. Or rather, it wouldn't do that in definitely (or just for long). *It possible that the Teensy is so much faster that it might re-enter a few times until the MCP23S17 got around to acknowledging that the interrupt condition had be cleared. I'm not advocating for this so, so I'll leave it at that.*

I believe ultimately what you want is to set a `FALLING` edge interrupt:
```c++
attachInterrupt(digitalPinToInterrupt(interruptPin1), GPIO1interrupt, FALLING);
```

Anyway, with `FALLING` the initial falling edge of the INTA/INTB line sets the interrupt condition in the Teensy (not MCP23S17) but it is cleared when your ISR executes.  So you will not keep re-entering the ISR. So your ISR will enter _once_ to set the global `volatile` flag. Later when you pick up on the set value of your global `volatile` flag(s), you need to call `.getInterruptValue()` (or otherwise read a pin) to clear the interrupt condition in your MCP23S17 (not Teensy) which will de-assert/raise INTA/INTB, at which point the ISR in the Teensy is ready for to get trigger by another falling edge of INTA/INTB.

It's also probably possible to do this with a `LOW`-level interrupt, but you'd have keep un-configuring them in the ISR and re-configuring them after you clear the MCP23S17's condition. Not sure that would be recommended. But, I think it's possible.

  [1]: https://www.arduino.cc/reference/en/language/functions/external-interrupts/attachinterrupt/
  [2]: https://github.com/MajenkoLibraries/MCP23S17/blob/6f6bac/src/MCP23S17.cpp#L503-L505
  [3]: https://github.com/MajenkoLibraries/MCP23S17/blob/6f6bac/src/MCP23S17.cpp#L348-L352


body:
I want to turn on my motor and count how many total rounds it has until my limit switch is switched on. After that, I want to count rounds counterclockwise until another limit switch is pushed. For this, I'm using [AccelStepper][1] and ezButton lib.

Here is my code:
```C++
      if ((limitSwitch_XV.getState() == LOW) && (limitSwitch_XE.getState() == LOW) && rightDirectionX) {
        while (1) {
          stepper1.step(-1);
          stageSizeX++;
        }
      }
```

But here I've got an error which says that I can't use `int` in `step()`: `'virtual void AccelStepper::step(long int)' is protected within this context stepper1.step(1);`

So how can I count the steps and go step by step to the given direction until I reach the limit switch with AccelStepper?

  [1]: https://www.airspayce.com/mikem/arduino/AccelStepper/classAccelStepper.html#aa4a6bdf99f698284faaeb5542b0b7514

title: How to count steps of a stepper motor with AccelStepper?

Answers: 1

body:
You get that error, because the `step()` method is protected in the AccelStepper class. It is not meant for calling by the user. AccelStepper instead wants you to state, what kind of movement you want (moving a specific distance/to a specific point/with a specific speed) and then frequently call the `AccelStepper.run()` method (or `AccelStepper.runSpeed()`), which will then execute the steps, when it is time to do so based on your planned movement.

---

If you want to solve your problem you have basically two ways to do this:

- With AccelStepper: Set the stepper to run at a specific speed in the correct direction, then in a loop calling `stepper1.runSpped()` and testing your limitswitch with `digitalRead()`. So something along the lines of:

        stepper1.setCurrentPosition(0);
        stepper1.setSpeed(20); // Change speed according to your needs, negative values let the motor rotate in the other direction
        while(limitSwitch_XV.getState() == HIGH){ // Assuming, that limit switch is not pressed when HIGH
            stepper1.runSpeed();
        }
        int revolutions = stepper1.currentPosition() / steps_per_revolution;

- or without AccelStepper: Depending on your stepper driver you can use a less sophisticated stepper library (like Arduinos `Stepper` library) or just control the stepper directly with `digitalWrite()` calls (to the Dir pin and to the Pulse pin). In that case you can do each step yourself, after each checking for the limit switch with `digitalRead()`. Something along the lines (I assume a stepper driver with dir pin and pulse pin, not one with multiple phase pins):

        digitalWrite(dir_pin, direction); // provide HIGH or LOW here depending on wanted direction
        int pos = 0;
        while(limitSwitch_XV.getState() == HIGH){
            digitalWrite(pulse_pin, HIGH);
            delayMicroseconds(10);
            digitalWrite(pulse_pin, LOW);
            pos++;
            delayMicroseconds(50); // Change this value according to the wanted speed
        }
        int revolutions = pos / steps_per_revolution;

Note, that both code snippets are totally untested and you need to build the surrounding code yourself. They only highlight the principle.


body:
I read [this article][1]. In the article, it uses A4 and A5 for I2C. But can I just use SCL and SDA pin directly in the Arduino UNO R3? And do I need a put-up resistor for SCL and SDA pin?

  [1]: https://playground.arduino.cc/Main/I2CBi-directionalLevelShifter/

title: Can i use SCL, SDA pin for I2C

Answers: 1

body:
Pins A4/A5 and the SCL/SDA pins are *the exact same pins* on the Arduino UNO R3. Not just "they perform the same function", but they are physically the same pins. It is one solid piece of metal from one pin to the other.

You don't *need* pullup resistors on the I2C pins because the `Wire` library turns on the internal pullups by default. However those internal pullups are about a tenth of the strength that I2C pullups *should* be, so I would recommend that you *do* add pullups, certainly for anything more than a couple of inches of wire.


body:
I have dual boot laptop, Windows 11 & Linux Mint 21 (default boot).  when running Arduino IDE 1.8.19 using Linux the port not accessible [from tools/port], but if I boot as windows, I can access the port from the Arduino IDE.

Other applications running in Linux can access the USB drive without issue (eg FreeCAD, PrusaSlicer). Arduino IDE is the only app so far with this USB issue.

"dialout" is in my list of groups

Arduino IDE was installed using apt

If I run lsusb when the nano is connected, i see the following extra entry

    Bus 003 Device 009: ID 1a86:7523 QinHeng Electronics CH340 serial converter

On another post it suggested running ls -l /dev/ttyUSB* and ls -l /dev/ttyACM*. For both I get the response "No such file or directory". The following files starting with tty* are in the /dev directory

```
tty    tty11  tty15  tty19  tty22  tty26  tty3   tty33  tty37  tty40  tty44  tty48  tty51  tty55  tty59  tty62  tty9       ttyS10  ttyS14  ttyS18  ttyS21  ttyS25  ttyS29  ttyS4  ttyS8
tty0   tty12  tty16  tty2   tty23  tty27  tty30  tty34  tty38  tty41  tty45  tty49  tty52  tty56  tty6   tty63  ttyprintk  ttyS11  ttyS15  ttyS19  ttyS22  ttyS26  ttyS3   ttyS5  ttyS9
tty1   tty13  tty17  tty20  tty24  tty28  tty31  tty35  tty39  tty42  tty46  tty5   tty53  tty57  tty60  tty7   ttyS0      ttyS12  ttyS16  ttyS2   ttyS23  ttyS27  ttyS30  ttyS6
tty10  tty14  tty18  tty21  tty25  tty29  tty32  tty36  tty4   tty43  tty47  tty50  tty54  tty58  tty61  tty8   ttyS1      ttyS13  ttyS17  ttyS20  ttyS24  ttyS28  ttyS31  ttyS7

```

If I tail the system log and plug the nano into the usb drive I get the following (the answer my be here but I cant see it).

```
Oct  7 17:17:14 HP-Envyl kernel: [ 8949.381626] usb 3-4: new full-speed USB device number 14 using xhci_hcd
Oct  7 17:17:14 HP-Envyl kernel: [ 8949.599105] usb 3-4: New USB device found, idVendor=1a86, idProduct=7523, bcdDevice= 2.64
Oct  7 17:17:14 HP-Envyl kernel: [ 8949.599107] usb 3-4: New USB device strings: Mfr=0, Product=2, SerialNumber=0
Oct  7 17:17:14 HP-Envyl kernel: [ 8949.599108] usb 3-4: Product: USB Serial
Oct  7 17:17:14 HP-Envyl kernel: [ 8949.601365] ch341 3-4:1.0: ch341-uart converter detected
Oct  7 17:17:14 HP-Envyl mtp-probe: checking bus 3, device 14: "/sys/devices/pci0000:00/0000:00:14.0/usb3/3-4"
Oct  7 17:17:14 HP-Envyl mtp-probe: bus: 3, device: 14 was not an MTP device
Oct  7 17:17:14 HP-Envyl kernel: [ 8949.601888] usb 3-4: ch341-uart converter now attached to ttyUSB0
Oct  7 17:17:14 HP-Envyl systemd[1]: Starting Braille Device Support...
Oct  7 17:17:14 HP-Envyl brltty[12613]: BRLTTY 6.4 rev BRLTTY-6.4 [https://brltty.app/]
Oct  7 17:17:14 HP-Envyl brltty[12613]: BRLTTY 6.4 rev BRLTTY-6.4 [https://brltty.app/]
Oct  7 17:17:14 HP-Envyl brltty[12613]: executing as the invoking user: root
Oct  7 17:17:14 HP-Envyl brltty[12613]: brltty: executing as the invoking user: root
Oct  7 17:17:14 HP-Envyl mtp-probe: checking bus 3, device 14: "/sys/devices/pci0000:00/0000:00:14.0/usb3/3-4"
Oct  7 17:17:14 HP-Envyl mtp-probe: bus: 3, device: 14 was not an MTP device
Oct  7 17:17:14 HP-Envyl brltty[12613]: CLDR open error: No such file or directory: /usr/share/unicode/cldr/common/annotations/en.xml
Oct  7 17:17:14 HP-Envyl brltty[12613]: brltty: CLDR open error: No such file or directory: /usr/share/unicode/cldr/common/annotations/en.xml
Oct  7 17:17:14 HP-Envyl brltty[12613]: brltty: possible cause: the package that defines the CLDR annotations directory is not installed
Oct  7 17:17:14 HP-Envyl brltty[12613]: brltty: emoji substitutiion won't be performed
Oct  7 17:17:14 HP-Envyl brltty[12613]: brltty: BrlAPI Server: release 0.8.3
Oct  7 17:17:14 HP-Envyl brltty[12613]: possible cause: the package that defines the CLDR annotations directory is not installed
Oct  7 17:17:14 HP-Envyl systemd[1]: Started Braille Device Support.
Oct  7 17:17:14 HP-Envyl brltty[12613]: emoji substitutiion won't be performed
Oct  7 17:17:14 HP-Envyl brltty[12613]: BrlAPI Server: release 0.8.3
Oct  7 17:17:14 HP-Envyl brltty[12613]: Linux Screen Driver:
Oct  7 17:17:14 HP-Envyl brltty[12613]: brltty: Linux Screen Driver:
Oct  7 17:17:14 HP-Envyl kernel: [ 8950.123164] input: BRLTTY 6.4 Linux Screen Driver Keyboard as /devices/virtual/input/input49
Oct  7 17:17:15 HP-Envyl brltty[12613]: USB configuration set error 16: Device or resource busy
Oct  7 17:17:15 HP-Envyl brltty[12613]: brltty: USB configuration set error 16: Device or resource busy
Oct  7 17:17:15 HP-Envyl brltty[12613]: USB interface in use: 0 (ch341)
Oct  7 17:17:15 HP-Envyl brltty[12613]: brltty: USB interface in use: 0 (ch341)
Oct  7 17:17:15 HP-Envyl ModemManager[1013]: <info>  [base-manager] port ttyUSB0 released by device '/sys/devices/pci0000:00/0000:00:14.0/usb3/3-4'
Oct  7 17:17:15 HP-Envyl ModemManager[1013]: <info>  [base-manager] couldn't check support for device '/sys/devices/pci0000:00/0000:00:14.0/usb3/3-4': Operation was cancelled
Oct  7 17:17:15 HP-Envyl kernel: [ 8950.239032] usb 3-4: usbfs: interface 0 claimed by ch341 while 'brltty' sets config #1
Oct  7 17:17:15 HP-Envyl kernel: [ 8950.239683] ch341-uart ttyUSB0: ch341-uart converter now disconnected from ttyUSB0
Oct  7 17:17:15 HP-Envyl kernel: [ 8950.239693] ch341 3-4:1.0: device disconnected
Oct  7 17:17:15 HP-Envyl brltty[12613]: NoSpeech Speech Driver:
Oct  7 17:17:15 HP-Envyl brltty[12613]: brltty: NoSpeech Speech Driver:
Oct  7 17:17:18 HP-Envyl rtkit-daemon[3252]: Supervising 10 threads of 3 processes of 1 users.
```

Does anyone have any idea what can cause this issue?

title: On Linux Min21, unable to access tools/port (grayed out)

Answers: 1

body:
OK, i can close this. brtty was the problem. I disabled it (found instructions below on another post)
```
systemctl stop brltty-udev.service
sudo systemctl mask brltty-udev.service
systemctl stop brltty.service
systemctl disable brltty.service
```
After logout and login, it works now.

Thanks for the help. I did not have this issue on Mint 20, so i am guessing that brtty was automatic in Mint 21


body:
I'm working on creating a simple ACK/NACK handshake between 2 Arduino's that will essentially go like this:

1. Arduino 1 signals Arduino 0 it is available
2. Arduino 0 sends a connect byte to Arduino 1 (say, 'c')
3. Arduino 1 sends a confirmation byte to Arduino 0 (say, 's')

This seems simple enough, so what I'm doing to avoid any kind of multithreading or callback functions is to use `Wire.requestFrom()`. From the wiki, this function "requests" the device at the specified address to send data. From what I understand, this "request" simply entails the master device simply blocking until it receives the necessary data. It doesn't seem to send any signal to the slave device that it should send anything, just does a simple wait. As such, I created a simple demo of this handshake between the two devices as follows:

```
// slave
#include <Wire.h>

void setup() {
  Serial.begin(9600);
  Wire.begin(1);
  Wire.requestFrom(0, 1, false);
  Serial.println("finished");
}
```

```
// master
#include <Wire.h>

bool last = false;

void setup() {
  Serial.begin(9600);
  Wire.begin(0);
  pinMode(2, INPUT);
}

void loop() {
  if (digitalRead(2) && !last) {
    Wire.beginTransmission(1);
    Wire.write('c');
    Wire.endTransmission(1);
  } else if (!digitalRead(2)) {
    last = false;
  }
  delay(1000);
}
```

Here, the master code waits on a signal (pin 2) (which is given by Arduino 1) that it is available, and then on connect, will send one connect byte to Arduino 1. In Arduino 1 (slave)'s code, I've placed the requestFrom call that should block until Arduino 0 sends that connect byte.

The problem here is that it's not actually blocking. Even before I've gotten a chance to run the master's code, the slave's "finished" output has instantly triggered. Am I understanding this function incorrectly or is there something wrong in my implementation?

title: Wire.requestFrom() not a blocking function, even though it should be(?)

Answers: 2

body:
Masters request data from the slave, not the other way around.

See <http://gammon.com.au/i2c>

Slaves set up a "receive" handler to be told that there is incoming data.

    Wire.onReceive (receiveEvent);

>  From what I understand, this "request" simply entails the master device simply blocking until it receives the necessary data.

Yes, but you don't have this request on the master, you have it on the slave. There is your problem.

body:
You completely misunderstand how I2C communication (that's what the `Wire` library does) works. I won't explain the full I2C interface here, since that is a bit too much for this answer.

`Wire.requestFrom()` doesn't block until it receives data. It will configure the I2C interface as master (when previously in slave mode this will be temporary). Then it enforces a start condition on the bus, sends the address of the slave and then sends a clock pulse for the acknowledgement bit. During this clock pulse the slave can pull the SDA line low and signal that way, that it is reachable. After that the master continues to generate the clock for all the bytes it wants, expecting the slave to control the SDA line. If the slave doesn't do that (for example because you didn't connect the `onRequest()` callback), then the received data will just be 1s (so each byte 0xFF).

So `Wire.requestFrom()` does only block for the time, that the transmission needs. If the slave doesn't acknowledge its address, the function will exit after that. The transaction will only need a few milliseconds either way.

> avoid any kind of multithreading or callback functions

On AVR based Arduinos (like the Uno or Nano) multithreading isn't really a thing (besides using a time sharing library, but still on only one core), though callbacks from interrupts are. And as long as you use the `Wire` library (and with it the I2C hardware interface of the microcontroller) you have to use interrupts and thus callback functions. And honestly there is normally no reason not to do that.

---

Another problem with what you are currently doing it, that both Arduinos act as masters on the bus. No two masters can send on the bus at the same time. While the I2C protocol has a way to determine, which master can send first, this is often implemented rather buggy. I don't know how good the `Wire` library is with this currently, but you should avoid a multi-master setup if possible.

---

A minor problem: The I2C address space has some reserved sections for special use. You can start your slave addresses at 8 (refer to the I2C specification on the web). Address 0 is meant as a general call address, so for master-write transactions, which target every slave on the bus. You shouldn't have a slave with that address.

---

**What to do now?** Just implement the code with the `Wire` library as it is meant, including the `onRequest()` callback function. Refer to the master-read example of the `Wire` library. Set the second Arduino as master and the first as slave. On the second Arduino you can call `Wire.requestFrom()` with the slaves address. This will trigger the `onReqest()` callback function on the first Arduino, where you can use `Wire.write()` to let the library send the desired data back to the master. On the master (Arduino 2) you an then read that data via `Wire.read()`. And thats it.


body:
I wrote [this][1] code to convert String to Hex Array.

    const char* hexstring = "0x21 0x73 0x10 0xfa 0x7a 0x00 0xff .../*40995 character long string*/....0xaa"
    void setup() {
        char* temp;
        //Serial.printf("%s",hexstring);
        unsigned int number[8199];

        number[0] = strtoul (hexstring,&temp,16);
        for(int i=1;i<8199;i++)
         number[i]= (int)strtoul(temp, &temp, 16);

        for(int i=0;i<8199;i++)
            {
                if(id)
                    printf("\n");
                printf("%d, ",number[i]);
            }
    }

    void loop(){
    }

But it is causing ESP32 to reboot.
[![enter image description here][2]][2]

Could anyone help me with the reason why?

  [1]: https://drive.google.com/file/d/12ImK6y2eZ9eO5znS2TJ3GHKRzaxjviwI/view?usp=sharing
  [2]: https://i.stack.imgur.com/K03W3.png

title: ESP32 Rebooting while converting String to Hex Array

Answers: 1

body:
```c++
void setup() {
    char* temp;
    //Serial.printf("%s",hexstring);
    unsigned int number[8199]; <----- too much.
```

So, you're trying to put a 32796 byte object on the stack. I don't know exactly why you're seeing the manifestation that you are, but I'm not surprised.

I just took an ESP32-CAM and started playing with different sizes and found that around 1800 (`unsigned int`s) is where things start to go sideways, failing occasionally rather than constantly.  By a 2000 count, it continually reboots with `rst:0xc (SW_CPU_RESET),boot:0x13 (SPI_FAST_FLASH_BOOT)` transitioning to `rst:0x10 (RTCWDT_RTC_RESET),boot:0x13 (SPI_FAST_FLASH_BOOT)
`  and later to very roughly around 5000 it becomes `rst:0x8 (TG1WDT_SYS_RESET),boot:0x13 (SPI_FAST_FLASH_BOOT)`

I _may_ fill out some details later if I look into it deeper. The ESP32 and SDK is complicated enough that there may well be a function can call that will permit a higher stack level. But this is mostly to satisfy curiosity.

Putting very large things (relative to the system size) on the stack is usually not done. I hesitate to try to tell you what exactly you should do; it wouldn't surprise me if you don't need this array at all for what you ultimately want to do, but that's a _different_ question). So, I'll just say get it off the stack through either dynamic memory allocation (e.g. through `new` or `malloc`), possibly using a smart pointer (e.g. `std::unique_ptr`) to manage that since those are available on the ESP32, or perhaps just making the variable either a `static` local or global. Or again if possible finding out why you might not need this array.

### Simple minimal change

So, I'm not going to tell you that this is a good idea, but a minimal change would be to `static` qualify this as `static unsigned int number[8199];` Then you won't get that reset cause, here, for this reason.

---

### Some details for anyone curious

If you want to see some of the guts, you look in the ESP32 core for Arduino where it [creates the task][1] that [ultimately runs `setup()`][2] for you. You can see that it calls [`getArduinoLoopTaskStackSize()`][3] returning [`ARDUINO_LOOP_STACK_SIZE`][4] which by default is `8192`. 8192 **bytes,** not `unsigned int`s. With `sizeof(unsigned int)` being 4, this is _very roughly_ in the vicinity of the 1800 `unsigned int`s where things started to fall apart in my testing above. Rather than chase down the configurion I just made a sketch that does `Serial.println(getArduinoLoopTaskStackSize());` and yeah, it prints 8192.

`getArduinoLoopTaskStackSize` is a [weakly defined][5] function which would allow something to redefine in elsewhere in the program to overload the default one. So, just out of curiosity I wrote one as follows:

```c++
size_t getArduinoLoopTaskStackSize(void) {
  size_t r_size = sizeof(unsigned int [8199]); // exactly the size your array
  r_size += r_size >> 3; // add about 1/8 (or 12.5%) extra
  return r_size;
}
```

It no longer crashes. Should you do this? Probably not. But, if you ever have a legitimate reason to put a 32K array on the stack on an ESP32 it _may_ be an option. I mostly just did this to see what would happen. It's barely been tested.

  [1]: https://github.com/espressif/arduino-esp32/blob/2.0.5/cores/esp32/main.cpp#L71
  [2]: https://github.com/espressif/arduino-esp32/blob/2.0.5/cores/esp32/main.cpp#L42
  [3]: https://github.com/espressif/arduino-esp32/blob/2.0.5/cores/esp32/main.cpp#L36-L38
  [4]: https://github.com/espressif/arduino-esp32/blob/2.0.5/cores/esp32/main.cpp#L14
  [5]: https://en.wikipedia.org/wiki/Weak_symbol


body:
TOF050C-VL6180X Sensor was not responding, so I checked it with a multi-meter, and the VIN, GND solder pins on it read 4.7V. Double-checked Mega voltage, without anything connected, and it shows stable 3.6V. Connected a different ToF and it works perfectly, with a 3.6V on it.

So that proves that sensor is damaged (might've powered it with 5V at first), but I don't understand how is it taking more than the regulated 3.3V? If it was shorted, it would read 0V, and if something burnt, it would be open circuit and show ~3.3V, right? So how is it just getting 4.7V out of nowhere? Any ideas on what I'm not understanding here?

Thank you!

**EDIT:** More info, tried to isolate issue as much as I could

**1)** The non-working sensor shows 4.7V
[![1) The non-working sensor shows 4.7V on multi-meter][1]][1]

**2)** The working sensor shows 3.4V and outputs distance to serial
[![Working sensor shows 3.4V on multi-meter][2]][2]

**3)** This is where it gets weird. I uploaded the simple blink sketch and now the working sensor shows 4.7V too

[![Working sensor shows 4.7V on multi-meter][3]][3]

**4)** So I tried **disconnecting the SDA/SCL**, while leaving power connected, with the blink sketch running, and it's back to 3.3V!

[![Arduino outputs 3.3V to sensor][4]][4]

**Tried the same steps with a different Mega, and **it always shows 3.3V, no matter the configuration!**

Now I'm very lost. So is the Arduino semi-damaged, with the I2C communication acting weird? Is it still safe to use with the project, if it *technically* works?

  [1]: https://i.stack.imgur.com/DXhSZl.jpg
  [2]: https://i.stack.imgur.com/qzoAHm.jpg
  [3]: https://i.stack.imgur.com/JpmM5m.jpg
  [4]: https://i.stack.imgur.com/kwlBbm.jpg

title: Arduino outputting 4.7V instead of 3.3V when using I2C communication/sensor?

Answers: 1

body:
The Arduino Wire [enables the internal pullup resistor][1] on SDA and SDL. The internal pull-ups are specified at 20k to 50k. So you *are* providing 5V (or there about) to the sensor, though through a high resistance connection. So, the voltage isn't coming from nowhere.

It is not unlikely that there protection/clamp diodes in the sensor IC or on the sensor board that connect these signals forward through the diode to the IC's 3.3v connection.

So your SCL/SDA can be seen as very weakly (through roughly 35k) trying to backfeed your 3.3V regulator which is probably just blocking the current. If the sensor/board is using no current to speak of, either because it just doesn't normally or because it's dead, you would measure 5V minus a diode drop, or roughly the 4.7V you're seeing.

If you assume the internal resistors are both at 20K as a "worst" case scenario for a calculation, the current needed through one to drop 5v to 3.3v is 85uA. So with 170uA load on the board that would drop the 3.3V pin  connection back to its 3.3V level. About 170uA will flow through a 20k resistor with 3.3V across it. So if you want experiment take any resistor from about 470ohms all the way to just shy of 20k in parallel with your 3.3V / GND measurement and see if your 4.7V measurement doesn't drop right down to the normal 3.3V output.

  [1]: https://github.com/arduino/ArduinoCore-avr/blob/1.8.5/libraries/Wire/src/utility/twi.c#L87-L89


body:
How does one read can packets from a VP230 Can Bus transceiver? I also have a MCP2515 which I've gotten to work, but the VP230 is a lot smaller.

I haven't been able to find any information about actually implementing the VP230, any help would be great.

title: VP230 CAN Bus Transceiver

Answers: 1

body: Welcome. You are talking two compatible CAN parts but they have different functions. The VP230 is the CAN bus bidirectional interface. This converts the signals on the CAN bus to logic signals your CAN controller can use. The MPC2515 is a CAN controller chip that talks to your microprocessor and the bus transceiver. The MCP2515 has only logic signals and is not compatible with the CAN bus. Together they make a good CAN bus interface. Both parts are 3V3 compatible.


body:
I have run into this issue where my code will upload to my Due but fails to execute. I have verified the code works on a SparkFun Redboard. The only code difference is that the SPI pin assignments have been appropriately changed. My code, for initial testing purposes, can run without any sort of attachments or additional boards. I do use or rather will be using SPI communication when I do wire up all of the instruments. The code currently handles not having anything connected just fine. The expected output as provided by running on the Redboard is below.

[![screen shot of desired serial monitor as produced by a redboard][1]][1]

Initially I thought that my code was running on the Due and failing to communicate serially, but when I tried to implement a simple blink routine near the beginning of the loop and even some things during setup, it became clear that the code was failing to make it through the "setup" function. I couldn't even get a serial print from the second line of the setup function. It is very clear that the code fully uploads based on both the IDE and the Rx/Tx LEDs on the board. I am using the correct port, and I am using the correct board selection and USB port on the board (the programming port nearest to the barrel plug jack).

I came across a number of posts and they either didn't address my issue or they didn't actually come to a conclusion. I did find some very simple test code post in a different topic (below). This code does run. I have also successfully run the "Blink" example code on the Due.

```
byte count = 0;

void setup() {
  Serial.begin(115200);
}

void loop() {
  Serial.print ("Count = ");
  Serial.println (count);
  count++;
  delay(500);
}
```

It was brought to my attention that there may be some libraries that don't play well with the Due, but even when I removed all immediately unnecessary libraries, I was unable to get the code to run on the Due.

The actual code for the project is shown below. There is some commented-out code that I tried to use for debugging. Also, I have split up the code into separate CPP and header files as that was what I was taught to do in college.

Does anyone know what is going on here? Does anyone know of a fix or workaround?

The code is provided in the follow order:

fluidized_bed_test.ino
Blower.cpp
Blower.h
Heater.cpp
Heater.h
Thermocouple.cpp
Thermocouple.h
control.cpp
control.h
fluidized_bed_test.h

**fluidized_bed_test.ino**

```
#pragma once
#include "Thermocouple.h"
#include "Heater.h"
#include "Blower.h"
#include "fluidized_bed_test.h"

#define MAX_MESSAGE_LEN 50

Thermocouple therm1(MOSIPin,MISOPin,CLKPin,CHIPSEL1,DRDYPIN1);
Thermocouple therm2(MOSIPin,MISOPin,CLKPin,CHIPSEL2,DRDYPIN2);
Thermocouple therm3(MOSIPin,MISOPin,CLKPin,CHIPSEL3,DRDYPIN3);
Heater heater(HEATERPIN);
Blower blower(BLOWERPIN);

void setup()
{
  Serial.begin(115200);
//  while (!Serial){}
  Serial.print("Shall we begin");
  SPI.begin();
  pinMode( MISOPin, INPUT );
  pinMode( MOSIPin, OUTPUT );
  pinMode( DRDYPIN1, INPUT );
  pinMode( CHIPSEL1, OUTPUT ); // Thermocouple 1
  pinMode( DRDYPIN2, INPUT );
  pinMode( CHIPSEL2, OUTPUT ); // Thermocouple 2
  pinMode( DRDYPIN3, INPUT );
  pinMode( CHIPSEL3, OUTPUT ); // Thermocouple 3
  pinMode( HEATERPIN, OUTPUT); // Heater
//  pinMode(LED_BUILTIN, OUTPUT);
//  pinMode(13, OUTPUT);

  therm1.setFaultMask();
  therm1.setBaseConfig();
  therm1.setColdOffset();
  therm1.setTemperatureFault();

  therm2.setFaultMask();
  therm2.setBaseConfig();
  therm2.setColdOffset();
  therm2.setTemperatureFault();

  therm3.setFaultMask();
  therm3.setBaseConfig();
  therm3.setColdOffset();
  therm3.setTemperatureFault();

  heater.setControl(0);
  blower.setControl(1);
  blower.setBlower(1);
  blower.setPID(255);
//  digitalWrite(LED_BUILTIN, LOW); //added to see if executing at all
//  delay(5000);
//  digitalWrite(LED_BUILTIN, HIGH); //added to see if executing at all
//  delay(5000);
  delay(200);
}

void loop()
{
  static float temperature1 = 0;
  static float temperature2 = 0;
  static float temperature3 = 0;
  static int blower_pid = 255;
  static int new_blower_pid = -1;
  static int remaining_char = 0;
  static int i = 0;
  static char inByte = 0;
  static char incoming_message[MAX_MESSAGE_LEN];
  temperature1 = therm1.getTemp();
  temperature2 = therm2.getTemp();
  temperature3 = therm3.getTemp();

  digitalWrite(LED_BUILTIN, LOW); //added to see if executing at all
//  delay(5000);

//  static int j = 0;
//  while(j < 10)
//  {
//  digitalWrite(LED_BUILTIN, LOW); //added to see if executing at all
//  delay(500);
//  digitalWrite(LED_BUILTIN, HIGH); //added to see if executing at all
//  delay(500);
//  j++;
//    }

 // Retrieve Thermocouple 1 temps
  Serial.println("Thermocouple 1 Temperature");
  Serial.println(temperature1);
  Serial.println("Cold Junction 1 Temperature");
  Serial.println(therm1.getColdTemp());

 // Retrieve Thermocouple 2 temps
  Serial.println("Thermocouple 2 Temperature");
  Serial.println(temperature2);
  Serial.println("Cold Junction 2 Temperature");
  Serial.println(therm2.getColdTemp());

// Retrieve Thermocouple 3 temps
  Serial.println("Thermocouple 3 Temperature");
  Serial.println(temperature3);
  Serial.println("Cold Junction 3 Temperature");
  Serial.println(therm3.getColdTemp());

  i = 0;

  while ( Serial.available() )
  {
    inByte = Serial.read();

    if ( inByte != '\n' && (i < MAX_MESSAGE_LEN - 1) )
    {
      incoming_message[i] = inByte;
      i++;
    }
    else
    {
      incoming_message[i] = '\0';
    }
  }
  new_blower_pid = atoi(incoming_message);
  digitalWrite(LED_BUILTIN, HIGH); //added to see if execturing at all
  delay(1000);
}
```

**Blower.cpp**

```
#pragma once
#include "Blower.h"

Blower::Blower(int pin)
{
  pinNum = pin;
  blowerState = 0;
  pidState = 0;
  pidValue = 255;
}

void Blower::setBlower( boolean state )
{
  blowerState = state;
  updateBlower();
}

void Blower::setControl(boolean state )
{
  pidState = state;
  updateBlower();
}

void Blower::setPID( int pid )
{
  pidValue = pid;
  updateBlower();
}

boolean Blower::isOn()
{
  return blowerState;
}

boolean Blower::getControl()
{
  return pidState;
}

int Blower::getPIDValue()
{
  return pidValue;
}

void Blower::updateBlower()
{
  if(blowerState)
  {
    if(pidState)
    {
      analogWrite(pinNum,pidValue);
    }
    else
    {
      analogWrite(pinNum,255);
    }
  }
  else
  {
    analogWrite(pinNum,255);
  }
}
```

**Blower.h**

```
#pragma once
#if ARDUINO >= 100
  #include "Arduino.h"
#else
  #include "WProgram.h"
#endif

class Blower
{
  public:
    Blower( int pin);
    void setBlower(boolean = false);
    void setControl(boolean = false);
    void setPID(int pid = 255);
    boolean isOn();
    boolean getPidState();
    boolean getControl();
    int getPIDValue();

  private:
    void updateBlower();

    boolean blowerState;
    boolean pidState;
    int pidValue;
    int pinNum;
};
```

**Heater.cpp**

```
#pragma once
#include "Heater.h"

Heater::Heater(int pin)
{
  pinNum = pin;
  heaterState = 0;
  pidState = 0;
  pidValue = 255;
}

void Heater::setHeater( boolean state )
{
  heaterState = state;
  updateHeater();
}

void Heater::setControl(boolean state )
{
  pidState = state;
  updateHeater();
}

void Heater::setPID( int pid )
{
  pidValue = pid;
  updateHeater();
}

boolean Heater::isOn()
{
  return heaterState;
}

boolean Heater::getControl()
{
  return pidState;
}

int Heater::getPIDValue()
{
  return pidValue;
}

void Heater::updateHeater()
{
  if(heaterState)
  {
    if(pidState)
    {
      analogWrite(pinNum,pidValue);
    }
    else
    {
      analogWrite(pinNum,255);
    }
  }
  else
  {
    analogWrite(pinNum,255);
  }
}
```

**Heater.h**

```
#pragma once
#if ARDUINO >= 100
  #include "Arduino.h"
#else
  #include "WProgram.h"
#endif

class Heater
{
  public:
    Heater( int pin);
    void setHeater(boolean = false);
    void setControl(boolean = false);
    void setPID(int pid = 255);
    boolean isOn();
    boolean getPidState();
    boolean getControl();
    int getPIDValue();

  private:
    void updateHeater();

    boolean heaterState;
    boolean pidState;
    int pidValue;
    int pinNum;
};
```

**Thermocouple.cpp**

```
#pragma once
#include "Thermocouple.h"

Thermocouple::Thermocouple(int mosiPin,int misoPin,int clkPin, int chslctPin, int drdy)
{
  SPI.begin();
  MOSI = mosiPin;
  MISO = misoPin;
  CLK = clkPin;
  CHSLCT = chslctPin;
  DRDY = drdy;
}

double Thermocouple::getTemp(int unitTemp)
{
  switch(unitTemp)
  {
    case 0:
      return readThermocouple();
      break;
    case 1:
      return readThermocouple() + 273.15;
      break;
    case 2:
      return readThermocouple()*1.8 + 32;
      break;
    case 3:
      return (readThermocouple() + 273.15) * 1.8 - 32;
      break;
  }
}

double Thermocouple::binaryTempConvert( int binaryResult, int byteNumber )
{
  double decimalAns = 0;
  int placeHolder = 0;
  int numbit = 0;
  while (numbit <= 7 )
  {
    placeHolder = 0;
    placeHolder = binaryResult & int(pow(2, numbit)+.5);
    if ( placeHolder != 0 )
    {
      if ( byteNumber == 3 && numbit <= 5 )
      {
      }
      else if ( numbit == 7 && byteNumber == 1 )
      {
        decimalAns = decimalAns*(-1);
      }
      else
      {
        decimalAns = decimalAns + pow(2,(((8*(4-byteNumber))-1)-(7-numbit)-12));

      }

    }
    numbit = numbit+1;
  }
  return decimalAns;
}

/*double Thermocouple::readThermocouple()
{
  double result = 0;
  unsigned int preresult1 = 0;
  unsigned int preresult2 = 0;
  unsigned int preresult3 = 0;

  SPI.beginTransaction(SPISettings(500000,MSBFIRST,SPI_MODE1));

  digitalWrite( CHSLCT, LOW );

  SPI.transfer(rLinThermByte2);
  preresult1 = SPI.transfer(0);

  SPI.transfer(rLinThermByte1);
  preresult2 = SPI.transfer(0);

  SPI.transfer(rLinThermByte0);
  preresult3 = SPI.transfer(0);

  digitalWrite( chipselectPin1, HIGH );
  SPI.endTransaction();

  result = binaryTempConvert( preresult1, 1 );
  result = result + binaryTempConvert( preresult2, 2 );
  result = result + binaryTempConvert( preresult3, 3 );

  return result;

}*/

double Thermocouple::readThermocouple()
{
  byte dataToSend;
  double result = 0;
  unsigned int preresult1 = 0;
  unsigned int preresult2 = 0;
  unsigned int preresult3 = 0;
  unsigned int preresult[] = {0,0,0};
  int i = 0;

  SPI.beginTransaction(SPISettings(500000,MSBFIRST,SPI_MODE1));

  /*digitalWrite( CHSLCT, LOW );

  dataToSend = rLinThermByte2;
  SPI.transfer(rLinThermByte2);
  preresult1 = SPI.transfer(0);

  digitalWrite( CHSLCT, HIGH );

  digitalWrite( CHSLCT, LOW );

  dataToSend = rLinThermByte1;
  SPI.transfer(rLinThermByte1);
  preresult2 = SPI.transfer(0);

  digitalWrite( CHSLCT, HIGH );

  digitalWrite( CHSLCT, LOW );

  dataToSend = rLinThermByte0;
  SPI.transfer(rLinThermByte0);
  preresult3 = SPI.transfer(0);

  digitalWrite( CHSLCT, HIGH );
  SPI.endTransaction();

  result = binaryTempConvert( preresult1, 1 );
  result = result + binaryTempConvert( preresult2, 2 );
  result = result + binaryTempConvert( preresult3, 3 );*/

  for( i; i<3; i++)
  {
    digitalWrite(CHSLCT, LOW);
    SPI.transfer(rLinThermByte2 + byte(i));
    preresult[i] = SPI.transfer(0);
    digitalWrite(CHSLCT,HIGH);
  }
  for( i = 0; i<3; i++)
  {
    result += binaryTempConvert(preresult[i],i+1);
  }
  lastTemp = result;
  return result;

}

bool Thermocouple::isReady()
{
  return !digitalRead(DRDY);
}

void Thermocouple::writeRegister( byte thisRegister, byte thisValue )
{
   digitalWrite( CHSLCT, LOW );
  SPI.beginTransaction(SPISettings(1000000,MSBFIRST,SPI_MODE1));

  SPI.transfer(thisRegister);
  SPI.transfer(thisValue);

  digitalWrite( CHSLCT, HIGH );
  SPI.endTransaction();

}

unsigned int Thermocouple::readRegister( byte thisRegister )
{

  byte inByte = 0;
  unsigned int result = 0;

  digitalWrite( CHSLCT, LOW );

  byte dataToSend = thisRegister;
  SPI.beginTransaction(SPISettings(1000000,MSBFIRST,SPI_MODE1));
  SPI.transfer(dataToSend);
  result = SPI.transfer(0b10101010);

  SPI.endTransaction();
  digitalWrite( CHSLCT, HIGH );

  return result;
}

void Thermocouple::setFaultMask(byte regFault)
{
  writeRegister(wfaultMask,regFault);
}

void Thermocouple::setBaseConfig(byte regOne, byte regTwo )
{
  writeRegister(wCNfig0,regOne);
  writeRegister(wCNfig1,regTwo);
}

void Thermocouple::setTemperatureFault(int lowCold, int highCold, double lowHot, double highHot )
{
  int i = 0;
  int value = 0;
  double placeHold = 0;
  double absTemp = abs(lowHot);
  char binOne = 0;
  char binTwo = 0;
  if( lowHot > -2074.9375 || lowHot < 2074.9375 )
  {
    for( i = -4; i < 11; i++)
    {

      if( abs(absTemp - placeHold) > abs(absTemp - placeHold + pow(2,i)) )
      {
        placeHold += pow(2,i);
        value = (value << 1) | 0b00000001;
      }
    }
    if( lowHot < 0 )
      value = value | 0b1000000000000000;
  }
  binOne = char(value >> 8);
  binTwo = char(value & 0b0000000011111111);
  writeRegister(wLinThermLowFaultThreshMSB, binOne);
  writeRegister(wLinThermLowFaultThreshLSB, binTwo);

  value = 0;
  placeHold = 0;
  absTemp = abs(highHot);
  binOne = 0;
  binTwo = 0;

  if( highHot > -2074.9375 || highHot < 2074.9375 )
  {
    for( i = -4; i < 11; i++)
    {

      if( abs(absTemp - placeHold) > abs(absTemp - placeHold + pow(2,i)) )
      {
        placeHold += pow(2,i);
        value = (value << 1) | 0b00000001;
      }
    }
    if( highHot < 0 )
      value = value | 0b1000000000000000;
  }
  binOne = char(value >> 8);
  binTwo = char(value & 0b0000000011111111);
  writeRegister(wLinThermHighFaultThreshMSB, binOne);
  writeRegister(wLinThermHighFaultThreshLSB, binTwo);

  binOne = 0;
  binTwo = 0;

  if( lowCold >= 0b11111111 && highCold <= 0b01111111 && highCold > lowCold )
  {
    binOne = char(lowCold);
    binTwo = char(highCold);

    writeRegister(wColdLowFaultThresh,binOne);
    writeRegister(wColdHighFaultThresh,binTwo);
  }

}

void Thermocouple::setColdOffset(double temp)
{
  int i = 0;
  char value = 0;
  double placeHold;
  double absTemp = abs(temp);
  if( temp > -7.9375 || temp < 7.9375 )
  {
    for( i = 2; i > -5; i--)
    {
      if( abs(absTemp - placeHold) > abs(absTemp - placeHold + pow(2,i)) )
      {
        placeHold += pow(2,i);
        value = value | int(pow(2,i+4)+.5);
      }
    }
    if( temp < 0 )
      value = value | 0b10000000;
  }
  writeRegister(wColdOffset, value);
}

double Thermocouple::getColdOffset()
{
  int placeHold = 0;
  int i;
  double result = 0;
  char regVal = readRegister(rColdOffset);
  for( i=0; i<7; i++)
  {
    placeHold = int(pow(2,i)+.5);
    if( regVal & placeHold )
      result += pow(2,i-4);
  }
  if( regVal & 0b10000000 )
    result *= (-1);
  return result;
}

double Thermocouple::getColdTemp()
{
  int i = 0;
  int tempReading = byte( readRegister(rColdTempMSB) );
  tempReading = tempReading << 8;
  tempReading = tempReading | byte( readRegister(rColdTempLSB) );
  double result = 0;

  for( i=-6;i<7;i++)
  {
    if (  tempReading & int(pow(2,i+8)+.5) )
    {
      result += pow(2,i);
    }
  }
  return result;
}

double Thermocouple::getLatestTemp()
{
  return lastTemp;
}

```

**Thermocouple.h**

```
#pragma once
#if ARDUINO >= 100
  #include "Arduino.h"
#else
  #include "WProgram.h"
#endif
#include <SPI.h>

// memory register WRITE addresses of MAX31856 thermocouple board
#define wCNfig0 0x80
#define wCNfig1 0x81
#define wfaultMask 0x82
#define wColdHighFaultThresh 0x83
#define wColdLowFaultThresh 0x84
#define wLinThermHighFaultThreshMSB 0x85
#define wLinThermHighFaultThreshLSB 0x86
#define wLinThermLowFaultThreshMSB 0x87
#define wLinThermLowFaultThreshLSB 0x88
#define wColdOffset 0x89
#define wColdTempMSB 0x8A
#define wColdTempLSB 0x8B

// memory register READ addresses of MAX31856 thermocouple board
#define rCNfig0 0x00
#define rCNfig1 0x01
#define rfaultMask 0x02
#define rColdHighFaultThresh 0x03
#define rColdLowFaultThresh 0x04
#define rLinThermHighFaultThreshMSB 0x05
#define rLinThermHighFaultThreshLSB 0x06
#define rLinThermLowFaultThreshMSB 0x07
#define rLinThermLowFaultThreshLSB 0x08
#define rColdOffset 0x09
#define rColdTempMSB 0x0A
#define rColdTempLSB 0x0B
#define rLinThermByte2 0x0C
#define rLinThermByte1 0x0D
#define rLinThermByte0 0x0E
#define rFaultStatus 0x0F
#ifndef THERMOCOUPLE_H
#define THERMOCOUPLE_H

class Thermocouple
{
  public:
    Thermocouple(int mosiPin,int misoPin,int clkPin, int chslctPin, int drdy);//{MOSI,MISO,CLK,CHSLCT,DRDY};
    double getTemp(int unitTemp = 0);
    double getLatestTemp();
    void setFaultMask(byte regFault = 0b00110011);
    void setBaseConfig(byte regOne = 0b10000010,byte regTwo = 0b00000011 );
    void setTemperatureFault(int lowCold = 0,int highCold = 50,double lowHot = 0,double highHot = 200);
    void setColdOffset(double temp = 0);
    double getColdOffset();
    double getColdTemp();
    bool isReady();

  private:
    unsigned int readRegister(byte);
    void writeRegister(byte,byte);
    double readThermocouple();
    double binaryTempConvert(int,int);
    double lastTemp;
    int MOSI,MISO,CLK,CHSLCT,DRDY;

};
#endif
```

**control.cpp**

```
#pragma once
#include "control.h"
// #include "Thermocouple.h"
// #include "Heater.cpp"
// #include "Blower.h"

void fluid_bed_control( Heater heater, Blower blower, double inlet_temp, double bed_temp)// double MAX_INLET_TEMP, double MAX_BED_TEMP, double MIN_BED_TEMP)
{
  if( inlet_temp > MAX_INLET_TEMP )
  {
    heater.setHeater(0);
    blower.setBlower(1);
  }
  else if( bed_temp > MAX_BED_TEMP )
  {
    heater.setHeater(0);
    blower.setBlower(1);
  }
  else if( bed_temp < MIN_BED_TEMP )
  {
    heater.setHeater(1);
    blower.setBlower(1);
  }

}
````

**control.h**

```
#pragma once
#include "Thermocouple.h"
#include "Heater.h"
#include "Blower.h"
#include "fluidized_bed_test.h"

void fluid_bed_control( Heater heater, Blower blower, double inlet_temp, double bed_temp);//, double max_inlet_temp, double max_bed_temp, double min_bed_temp);
```

**fluidized_bed_test.h**

```
#pragma once
//#include <TimerOne.h>
//#include <Chrono.h>
//#include <LightChrono.h>
#include <SPI.h>
//#include <LiquidCrystal.h>
//#include <Wire.h> // Include the I2C library (required)
//#include <SparkFunSX1509.h> // Include SX1509 library

#define MAX_INLET_TEMP 82.2
#define MIN_INLET_TEMP 68.0
#define MAX_BED_TEMP 72.0
#define MIN_BED_TEMP 68.0

// pinout of redboard

// #define scrnPin1 1
// #define scrnPin2 2
// #define scrnPin3 3
// #define scrnPin4 4
// #define scrnPin5 5
// #define scrnPin6 6
#define DRDYPIN3 5
#define CHIPSEL3 6
#define DRDYPIN2 7
#define CHIPSEL2 8
#define DRDYPIN1 9
#define CHIPSEL1 10
//#define MOSIPin 11
//#define MISOPin 12
//#define CLKPin 13
#define MOSIPin 75
#define MISOPin 74
#define CLKPin 76
// #define SCRNCOM A0
// #define FLOATPIN1 A1
// #define FLOATPIN2 A2
// #define VALVEPIN1 A3
// #define VALVEPIN2 A4
#define HEATERPIN 4
#define BLOWERPIN 3

// pinout of I2C board
// #define MOTORPIN1 20
// #define MOTORPIN2 21
// #define FAULTPIN1 22
// #define FAULTPIN2 23

struct ProcessState
{
  bool safetyFlag;
  bool fillState;
  bool firstTime;
  bool standBy;
  bool warmUp;
  bool pasteurize;
  bool coolDown;
  bool emptyState;
  bool standByEmpty;
};
```

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

title: Code uploads to Due and fails to execute but runs on Redboard

Answers: 0


body:
The below reading data from API:

    #include <WiFi.h>
    #include <HTTPClient.h>
    #include <ArduinoJson.h>

    const char* ssid = "****";
    const char* pass = "****";

    void setup()
    {
      Serial.begin(115200);
      WiFi.begin(ssid, pass);
      Serial.print("COnnecting");

      while (WiFi.status() != WL_CONNECTED) {
        Serial.print(".");
        delay(500);
      }

      Serial.print("\nIP Address");
      Serial.println(WiFi.localIP());
    }

    void loop() {
      const char* root_0_id ;
      const char* root_0_Title ;
      if (WiFi.status() == WL_CONNECTED)
      {
        long rnd = random(1, 3);
        HTTPClient client;

        client.begin("https://6336d6c365d1e8ef267481aa.mockapi.io/api/bitmap/images?id=1");
        int httpCode = client.GET();

        if (httpCode > 0) {
          String payload = client.getString();
          Serial.println("\nstatuscode: " + String(httpCode));
          if (payload == "[]")
            Serial.println("\nNOT FOUND");
          else
          {

            DynamicJsonDocument doc(49152);
            DeserializationError error = deserializeJson(doc, payload);
            if (error) {
              Serial.print("deserializeJson() failed: ");
              Serial.println(error.c_str());
              return;
            }

            root_0_id = doc[0]["id"]; // "41"
            root_0_Title = doc[0]["Bitmap"];

            Serial.print("\n\nData : ");
            Serial.println(root_0_Title);

            Serial.println(sizeof(root_0_Title));
            client.end();
            dataReceived = 1;
            delay(10000);

          }

        }
        else {
          Serial.println("Error on HTTP request");
        }
      }
    }

I need help with parsing the `const char* root_0_Title="0x21,0x10,0xfa,0x7a,0xff"`, to uint8_t[5]={0x21, 0x10, 0xfa, 0x7a, 0xff}?

title: Conversion from `const char* datac="0x21,0x10,0xfa,0x7a,0xff";` to `uint8_t datat[]={0x21, 0x10, 0xfa, 0x7a, 0xff}`

Answers: 1

body:
you can use [strtok][1] (string tokenizer) and [strtol][2] (string to long) C functions.

```
  int count = 0;
  uint8_t bytes[MAX_SIZE];
  char* tok = strtok(root_0_Title, ",");
  while (tok != NULL) {
    bytes[count++] = strtol(tok, NULL, 16);
    tok = strtok(NULL, ",");
  }
```

  [1]: https://cplusplus.com/reference/cstring/strtok/
  [2]: https://cplusplus.com/reference/cstdlib/strtol/


body:
I have 3 LED chains which are all mapped to concentric rings. Each ring has a its own 2D array with the chain number & LED number. I have a function that is passed a ring array and then lights the appropriate LED. I'm using `FastLED`

    void lightUp(int ring_arr[][2], int i, int col){

      if(ring_arr[i][0] == 0){
          L0[ring_arr[i][1]] = CHSV(col, 255, 255);
        }
        if(ring_arr[i][0] == 1){
          L1[ring_arr[i][1]] = CHSV(col, 255, 255);
        }
        if(ring_arr[i][0] == 2){
          L2[ring_arr[i][1]] = CHSV(col, 255, 255);
      }
    }

This works fine BUT only if its called once in `loop()` if I make a 2nd call none of the LEDs light up. So I can light up 1 ring at a time but if I try to light up 2 or more then nothing lights up. Anyone see anything obvious that I'm overlooking?

The full code listing,

    #include <FastLED.h>

    #define NELEMS(x)  (sizeof(x) / sizeof((x)[0]))
    #define DATA_0 5
    #define DATA_1 6
    #define DATA_2 7
    #define NUM_LEDS 50

    CRGB L0[NUM_LEDS];
    CRGB L1[NUM_LEDS];
    CRGB L2[NUM_LEDS];

    // Rings
    int ring_1[][2] = {{0,0}, {0,1},  {0,2},  {0,3},  {1,49},
                       {1,28}, {1,29}, {1,30}, {1,31}, {1,32},
                       {1,23}, {1,24}, {1,25}, {1,26}, {1,27},
                       {1,2},  {1,3},  {1,4},  {1,5},  {1,6},
                       {1,0},  {1,1},  {2,0},  {2,1},  {2,2},
                       {2,19}, {2,20}, {2,21}, {2,22}, {2,23},
                       {2,24}, {2,25}, {2,26}, {2,27}, {2,28},
                       {2,45}, {2,46}, {2,47}, {2,48}, {2,49},
                       {0,29}, {0,28}, {0,27}, {0,26}, {0,25},
                       {0,4},  {0,5},  {0,6},  {0,7},  {0,8}};

    int ring_2[][2] = {{1,48}, {1,33}, {1,22}, {1,7},  {2,3},
                       {2,18}, {2,29}, {2,44}, {0,24}, {0,9}};

    int ring_3[][2] = {{1,47}, {1,34}, {1,21}, {1,8},  {2,4},
                       {2,17}, {2,30}, {2,43}, {0,23}, {0,10}};

    int ring_4[][2] = {{1,46}, {1,35}, {1,20}, {1,9}, {2,5},
                       {2,16}, {2,31}, {2,42}, {0,22}, {0,11}};

    int ring_5[][2] = {{1,45}, {1,36}, {1,19}, {1,10}, {2,6},
                       {2,15}, {2,32}, {2,41}, {0,21}, {0,12}};

    int ring_6[][2] = {{1,44}, {1,37}, {1,18}, {1,11}, {2,7},
                       {2,14}, {2,33}, {2,40}, {0,20}, {0,13}};

    int ring_7[][2] = {{1,43}, {1,38}, {1,17}, {1,12}, {2,8},
                       {2,13}, {2,34}, {2,39}, {0,19}, {0,14}};

    int ring_8[][2] = {{1,42}, {1,39}, {1,16}, {1,13}, {2,9},
                       {2,12}, {2,35}, {2,38}, {0,18}, {0,15}};

    int ring_9[][2] = {{1,41}, {1,40}, {1,15}, {1,14}, {2,10},
                       {2,11}, {2,36}, {2,37}, {0,17}, {0,16}};
    // Colours
    int col_1 = 0;
    int col_2 = 160;
    int col_3 = 96;

    void setup(){

       // LED set up
       FastLED.addLeds<WS2811,DATA_0,RGB>(L0, NUM_LEDS);
       FastLED.addLeds<WS2811,DATA_1,RGB>(L1, NUM_LEDS);
       FastLED.addLeds<WS2811,DATA_2,RGB>(L2, NUM_LEDS);
       FastLED.setBrightness(255);
       clearAll();
    }

    void loop()
    {

      for(int i; i < NELEMS(ring_1); i++){
        lightUp(ring_1, i, col_1);
      }

      for(int i; i < NELEMS(ring_2); i++){

    //    lightUp(ring_2, i, col_2); // if I uncomment any of these
    //    lightUp(ring_3, i, col_3); // no LEDs light up
    //    lightUp(ring_4, i, col_1);
    //    lightUp(ring_5, i, col_2);
    //    lightUp(ring_6, i, col_3);
    //    lightUp(ring_7, i, col_1);
    //    lightUp(ring_8, i, col_2);
    //    lightUp(ring_9, i, col_3);

      }

      FastLED.show();
      delay(1000);
    }

    void clearAll(){
      for(int i; i < NUM_LEDS; i++){
        L0[i] = CHSV(0, 0, 0);
        L1[i] = CHSV(0, 0, 0);
        L2[i] = CHSV(0, 0, 0);
      }
      FastLED.show();
    }

    void lightUp(int ring_arr[][2], int i, int col){

      if(ring_arr[i][0] == 0){
          L0[ring_arr[i][1]] = CHSV(col, 255, 255);
        }
        if(ring_arr[i][0] == 1){
          L1[ring_arr[i][1]] = CHSV(col, 255, 255);
        }
        if(ring_arr[i][0] == 2){
          L2[ring_arr[i][1]] = CHSV(col, 255, 255);
      }
    }

title: Function call only works if called once

Answers: 1

body:
Your `for` loops are missing an initialization. You should write

```c++
for (int i = 0; i < NELEMS(ring_1); i++)
```

but you missed the `= 0` part. This means the `i` variable ends up
uninitialized, and contains whatever was left in this memory location by
whatever used that memory before. The behavior in such situation is
generally unpredictable. However, one may guess that the `i` of the
second loop could be allocated in the same spot as the `i` of the first
loop. If this happens, then the second loop starts at `i=3` and ends up
being an empty loop.

As a (completely unrelated) side note, you could gather your three `L*`
arrays into a single 2D array. This would make `lightUp()` significantly
simpler:

```c++
void lightUp(int ring_arr[][2], int i, int col) {
    L[ring_arr[i][0]][ring_arr[i][1]] = CHSV(col, 255, 255);
}
```

or maybe it would be clearer like this:

```c++
void lightUp(int *location, int col) {
    L[location[0]][location[1]] = CHSV(col, 255, 255);
}
```

To be called as `lightUp(ring_1[i], col_1);`.


body:
I am making a 7x10 led matrix and I am having problems with the shiftout function. It is only able to show me the output in one shiftout register at a time. How can I fix it?
[![enter image description here][1]][1]

For example:
```arduino
void setup(){
    // PORTB as output.
    // Pin 13: Clock 74HC595
    // Pin 12: Latch
    // Pin 11: Data
    // Pin 10: Reset
    // Pin 9: Clock CD4017
    DDRB = 0b111111;
    // Makes sure the 4017 value is 0.
    PORTB = 0b100;
    delayMicroseconds(5);
    PORTB = 0;
}

void loop(){
  shiftOut(11, 13, LSBFIRST, 0b1000111101);
  PORTB = 0b10000;
  delayMicroseconds(800);
  PORTB = 0;
  delay(10000);
}
```
This is the output it produces:

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

But with numbers of 8 bits or less the output is displayed correctly.

shiftOut(11, 13, LSBFIRST, 0b10001111);
[![enter image description here][3]][3]

  [1]: https://i.stack.imgur.com/uxGrU.png
  [2]: https://i.stack.imgur.com/9AXCu.png
  [3]: https://i.stack.imgur.com/DBcas.png

title: Shiftout only handles one shift register at a time

Answers: 2

body:
Have a look at the implementation of `shiftOut()` (you can find it where you installed the Arduino IDE in the file `hardware/arduino/avr/cores/arduino/wiring_shift.c`):

    void shiftOut(uint8_t dataPin, uint8_t clockPin, uint8_t bitOrder, uint8_t val)
    {
      uint8_t i;

      for (i = 0; i < 8; i++)  {
        if (bitOrder == LSBFIRST) {
          digitalWrite(dataPin, val & 1);
          val >>= 1;
        } else {
          digitalWrite(dataPin, (val & 128) != 0);
          val <<= 1;
        }

        digitalWrite(clockPin, HIGH);
        digitalWrite(clockPin, LOW);
      }
    }

Do you see, that the value (parameter `val`) is of type `uint8_t`, so only 1 byte big? And do you see, that the for loop only counts to 8 (one iteration for each bit in a byte)? This means, that the `shiftOut()` function only handles one byte at a time. When you want to shift out more bits than 8, you need to call it repeatedly.

In your first example the code behaves accordingly. The provided data gets cast to `uint8_t`, cutting away the upper 2 bits.

body:
`shiftOut` works on bytes. To do more than one byte you have to do more than one `shiftOut`. Also you have to take note of the bit ordering. You should shift the most significant bit first, not the least.

For example, this:

```c++
  shiftOut(11, 13, LSBFIRST, 0b1000111101);
```
should be:
```c++
  shiftOut(11, 13, MSBFIRST, 0b10);
  shiftOut(11, 13, MSBFIRST, 0b00111101);
```


body:
I am trying to vary the speed of a 2-wire fan by using a Arduino Uno and only a potentiometer.

Initially, I assumed that I could go about doing so by using a code that I used for dimming an LED. When I have run the code and varied the potentiometer, the LED on the power supply changed but, the fan did not come on. I assume that this was due to an error in the first code.

In the second code, the fan also did not come on. I am unsure if it was my wiring. I have an voltage supply connected to a breadboard to power the fan.

Additionally, would I require a mosfet or transistor despite using a potentiometer? This could have also be the problem regarding my second attempt.

**First Code Attempt:**
```
int potPin=A2;
int gPin=9;
int potVal;
float LEDVal;
int dt=250;
void setup() {
  // put your setup code here, to run once:
pinMode(potPin, INPUT);
pinMode(gPin, OUTPUT);
Serial.begin(9600);
}

void loop() {
  // put your main code here, to run repeatedly:
potVal=analogRead(potPin);
LEDVal=(255./1023.)*potVal;
analogWrite(gPin,LEDVal);
Serial.println(LEDVal);
delay(dt);
}
```
**Second Code:**

```const byte CONTROL = 9;
int reading;
int value;

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

void loop() {
  reading = analogRead(POTENTIOMETER);
  value = map(reading, 0, 1024, 0, 255);
  analogWrite(CONTROL, value);
}```

title: How do I control the speed of a 2-wire fan with an Arduino and only a potentiometer?

Answers: 1

body:
Like people have already mentioned in the comments, you likely need to add a FET to drive the fan. The Arduino simply can't put provide the current required to drive the fan. According to the Arduino documentation, the microcontroller can only provide 20mA per output pin, which is enough to drive LEDs but not fan motors.

Luckily, there is a tutorial on the Arduino website for driving motors with PWM through a FET.
https://docs.arduino.cc/learn/electronics/transistor-motor-control

The following program is adapted from the ["Analog In, Out Serial" built-in example][1] and should be sufficient to control the speed of the motor.

<!-- language-all: lang-C++ -->

    // These constants won't change. They're used to give names to the pins used:

    const int analogInPin = A0;  // Analog input pin that the potentiometer is attached to

    const int analogOutPin = 9; // Analog output pin that the FET is attached to

    int sensorValue = 0;        // value read from the pot
    int outputValue = 0;        // value output to the PWM (analog out)

    void setup() {

    // declare the ledPin as an OUTPUT:
    pinMode(analogOutPin, OUTPUT);
    }

    void loop() {

    // read the analog in value:
    sensorValue = analogRead(analogInPin);

    // map it to the range of the analog out:
    outputValue = map(sensorValue, 0, 1023, 0, 255);

    // change the analog out value:
    analogWrite(analogOutPin, outputValue);

    // wait 2 milliseconds before the next loop for the analog-to-digital
    // converter to settle after the last reading:
    delay(2);
    }

This program has not been tested and is intended as an example. Make sure that the output for the FET is wired to a pin that can output PWM. Then make sure that your program is referencing the correct pin.

Make sure that your power supply has enough power to control the fan motor as well.

Here are some wiring diagrams from the tutorial webpage.

[![Transistor Motor Control Diagram][2]][2]
[![Transistor Motor Schematic][3]][3]

Note: The particular fan that you are using might not be able to be driven by PWM and you should seek out and read the relevant documentation for the fan.

  [1]: https://docs.arduino.cc/built-in-examples/analog/AnalogInOutSerial
  [2]: https://i.stack.imgur.com/tve31.png
  [3]: https://i.stack.imgur.com/3WuXI.png


body:
I have a function that accept an `HardwareSerial` class as argument:

    void ProcessLine(HardwareSerial *serial, char *line)
    {
        // do something
        serial->write("blablabla");
    }

In my code I also have a `BluetoothSerial` that shares the required functions (i.e. `write()`) with `HardwareSerial`.

To avoid to duplicate the code of my `ProcessLine()` that is quite long, is there a way to "cast" a `BlutoothSerial` to a `HardwareSerial`?

title: "Cast" BluetoothSerial to HardwareSerial

Answers: 1

body:
No, you don't "cast" between them. Instead you make use of *polymorphism*.

In the Arduino framework most classes fit into a "tree" with similar classes "hanging off" a common parent "branch".  In this case both `BluetoothSerial` and `HardwareSerial`, being both serial classes, are both children of the `Stream` class.  Indeed it is this `Stream` class (which itself is a child of the `Print` class) which gives these objects most of their functions.

So unless you *need* access to some function that is specific to the `HardwareSerial` class (such as the `.begin(...)` function) you should always work up the tree to the class that provides the most restrictive set of functions that suit your needs. In this case, since you are only printing data, it would be the `Print` class.  If you were reading data you would choose the `Stream` class.

So if you change your function to accept `Print *serial` instead of `HardwareSerial *serial` then it will accept *any* object that ultimately inherits from the `Print` object - so any serial objects, any network stream objects, etc.


body:
Just discovered this. When I cast an int to a char inside a Serial.print statement it costs way less program memory. I'm not sure why. Could someone explain this to me?
In the following example the difference is 228 bytes!

```
Serial.print(1); // 1676 bytes program storage space. 184 bytes of dynamic memory.
```

```
Serial.print((char) (48 + 1)); // 1448 bytes program storage space. 184 bytes of dynamic memory.
```
EDIT: Adding from different comments:
```
Serial.print('1'); // Sketch uses 1448 bytes program memory, 184 bytes dynamic memory
```
```
Serial.write(48 + 1); // Sketch uses 1448 bytes program memory, 184 bytes dynamic memory
```
EDIT: For an int > 9, adding quotes in following example saves 218 bytes program memory but adds 4 bytes to dynamic memory usage.
```
Serial.print(123); // 1676/184 bytes
Serial.print("123"); // 1458/188 bytes
Serial.print(String(123)); // 2772/194 bytes
```
EDIT2: Max digits in Arduino-uno int is 5(?). You save 80 bytes by converting it to a char array, in comparison to just printing the integer:
```
Serial.print(12345); // 1676/184 bytes
```
```
char digits[5];
int number = 12345;
for (int i = 4; i >= 0; i--) {
  digits[i] = (number ) + 48;
  number /= 10;
}
Serial.print(digits); // 1596/184 bytes
```
To test for yourself, uncommenting one or the other:

```
void setup() {
  // put your setup code here, to run once:
  Serial.begin(9600);
  Serial.print(1); // uses 1676/184 bytes
  //. Serial.print((char) (48 + 1)); // uses 1448/184 bytes
  //  Serial.print('1'); // uses 1448/184 bytes
  //  Serial.write(48 + 1); // 1448/184 bytes
  //  Serial.print(123); // 1676/184 bytes
  //  Serial.print("123"); // 1458/188 bytes
  //  Serial.print(String(123)); // 2772/194 bytes
  //  Serial.print(12345); // 1676/184 bytes | 1676/184
  //  Serial.print("12345"); // 1458/188 bytes | 1460/190
  //  char buff[5];
  //  itoa(12345, buff, 10);
  //  Serial.print(buff); // 1604/184 bytes
  char digits[5];
  int number = 12345;
  for (int i = 4; i >= 0; i--) {
    digits[i] = (number ) + 48;
    number /= 10;
  }
  Serial.print(digits); // 1596/184 bytes
}
void loop() {
  // put your main code here, to run repeatedly:

}
```
EDIT: Second question: Shouldn't this be optimised somehow? Or should I always take care of this myself? And why/how? ;)

**the chars 0-9 have a decimal value of 48-57 in the Ascii table, hence (char)(48 + 0-9) prints 0-9*

title: Why does Serial.print(1) cost 228 bytes more program memory compared to Serial.print((char)(48+1))?

Answers: 1

body:
The difference is simply this:

* Print this character

and

* Interpret this integer as a sequence of digits, work out the ASCII characters that represent each digit in turn, and print them.

As you can see even just writing out what the second one does takes more words. Printing an integer is a lot more work than just printing one character.  Think about what it takes to print the value 2034578 and how you would do that given that you can only output individual numbers 0-9 and the data isn't stored as the numbers 0-9 but a series of just 0 and 1...

It takes work. Lots of work.


body: I'm trying to install https://github.com/JiriBilek/ESP_ATMod onto an ESP8266. The sketch has Includes to many libraries. Those libraries have includes to other libraries and so on. Do I have to manually follow all these dependencies and download them to compile and upload my sketch? Or is there an easier way.

title: ESP_ATMod and its many library dependencies

Answers: 1

body:
An Arduino sketch is a folder not a file. The ESP_ATMod sketch has 11 files:
```
asnDecode.cpp
asnDecode.h
command.cpp
command.h
debug.h
ESP_ATMod.h
ESP_ATMod.ino
settings.cpp
settings.h
WifiEvents.cpp
WifiEvents.h
```

The sketch doesn't include libraries which would require installation. It uses only libraries bundled with the esp8266 platform: EEPROM, ESP8266mDNS, ESP8266WiFi and LittleFS. You don't have to install any libraries.

You can download all the files at once with "Download ZIP":

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

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


body:
I have this HT16K33 4 Digit 14-segment display I got brand new.
I connected it to my Arduino UNO, wired it up and uploaded some quick test code.
However, the display looks completely broken (see image below), only some segments turn on.

[![broken display][1]][1]

I soldered the connection pins to the HT16K33 board (see picture below). My solder isn't the best but it also shouldn't be too bad.

[![Solder][2]][2]

I did a quick resistance check on the connection pins to see if the pins were soldered correctly, and they seemed good. I'm not too sure how to test the ji2c pin though...

[![multimeter_test][3]][3]

Here is the Wiring on my breadboard:

[![Wiring][4]][4]

Finally here is the code i'm currently using:

    #include "HT16K33.h"
    #include <Wire.h>
    HT16K33 seg(0x070);

    void setup() {
      // put your setup code here, to run once:
      Serial.begin(9600);
      Wire.begin();
      if(!seg.begin()){
        Serial.println("ERROR");
        while(1);
      }
      Wire.setClock(100000);

      Serial.println("displayTest()");
      seg.displayOff();
      delay(1000);

      seg.displayOn();
      seg.displayClear();
      seg.displayInt(5);
    }

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

    }

I'm a bit troubled here and confused at what's going on... Help would be greatly appreciated

  [1]: https://i.stack.imgur.com/ylxVf.jpg
  [2]: https://i.stack.imgur.com/ECc5T.jpg
  [3]: https://i.stack.imgur.com/wYMke.jpg
  [4]: https://i.stack.imgur.com/Qmdv8.jpg

title: Display issues with 4 Digit, 14 segment

Answers: 1

body:
so @6v6gt's comment made me re-search for a library for a 14-segment HT16K33. It seems he/she was in the money since it started working after switching library. While I couldn't find any yesterday, I found this page today which covers 7-segment and 14-segment HT16K33:
https://learn.adafruit.com/adafruit-led-backpack/0-54-alphanumeric?view=all#library-reference-3052482

So I switched from the HT16K33 library to the "Adafruit_LEDBackpack" and "Adafruit_GFX" Libraries.

[![leds working][1]][1]

Code for those wondering:

    #include <Wire.h>
    #include <Adafruit_GFX.h>
    #include "Adafruit_LEDBackpack.h"

    Adafruit_AlphaNum4 alpha4 = Adafruit_AlphaNum4();

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

    alpha4.begin(0x70);  // pass in the address

    alpha4.writeDigitAscii(0, 'A');
    alpha4.writeDigitAscii(1, 'B');
    alpha4.writeDigitAscii(2, 'C');
    alpha4.writeDigitAscii(3, 'D');
    alpha4.writeDisplay();
    }

    void loop() {
    }

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

One question I have is (which is an entirely different subject), how do I go from here to rotate the letters and alphabet 180 degrees?


body:
I have an issue with this example https://github.com/BareConductive/mpr121/tree/public/MPR121/Examples/SimpleTouch when trying to upload it. Also, there was an issue when compiling it, however, the arduino suggested the change (wrong naming) that made the code compile. However, no upload. I have tried both boards available and both ports available *that are showing as options.

I get this verbose output:

```
processing.app.debug.RunnerException
 at cc.arduino.packages.uploaders.SerialUploader.uploadUsingPreferences(SerialUploader.java:152)
 at cc.arduino.UploaderUtils.upload(UploaderUtils.java:77)
 at processing.app.SketchController.upload(SketchController.java:732)
 at processing.app.SketchController.exportApplet(SketchController.java:703)
 at processing.app.Editor$UploadHandler.run(Editor.java:2061)
 at java.lang.Thread.run(Thread.java:748)
Caused by: processing.app.SerialException: Error touching serial port '/dev/cu.BLTH'.
 at processing.app.Serial.touchForCDCReset(Serial.java:107)
 at cc.arduino.packages.uploaders.SerialUploader.uploadUsingPreferences(SerialUploader.java:136)
 ... 5 more
Caused by: jssc.SerialPortException: Port name - /dev/cu.BLTH; Method name - openPort(); Exception type - Port busy.
 at jssc.SerialPort.openPort(SerialPort.java:164)
 at processing.app.Serial.touchForCDCReset(Serial.java:101)
 ... 6 more
```

Thank you in advance for any help.

title: Touch Board from Bare Conductive not uploading arduino code example

Answers: 0


body:
I am using a **Arduino MKR 1010 Wifi** board to control **4 servo** (PS-1109MG). All the circuit is powered by **4 AA rechargeable batteries** (1.2V * 4). Arduino is powered through the **Vin port**.

Below is a circuit just to show how they are connected (board type and other details is not correct).
[![circuit][1]][1]

When all the servos move, the arduino's LED oscillates in intensity. I deduced that the servos have a high instantaneous current consumption and the voltage of the batteries drops too much. I measured this with an oscilloscope.

[![scope image][2]][2]

The voltage drops to around 4V when the servos try to move. When the Arduino MKR is powered from the usb port and the servos from the batteries, everything works fine.

How can I reduce the voltage drop on the batteries, to use them as the only power source?
Could I use some electrolytic capacitors to reduce the voltage drop?

  [1]: https://i.stack.imgur.com/dnUag.jpg
  [2]: https://i.stack.imgur.com/Dw7r4.png

title: Voltage drop when power from AA batteries

Answers: 3

body:
Consider several options:
 1. Larger batteries.  The type of battery was not specified.  For comparison [a NiMH AA is on average about 800 mAh where a NiMH D is on average about 6600 mAh][1].
 2. Use two sets of batteries.  Connect both battery grounds, all the servo grounds and the Arduino ground together.  Only connect the positive of one set of batteries to the Arduino.  Only connect the positive of the other set of batteries to the servos.  Do not connect the positive Arduino terminal with the positive servo terminals!
 3. Using software, only operate one servo at a time.  Some (most) servos will stop moving if the position pulse is not seen by the servo.

  [1]: https://en.wikipedia.org/wiki/List_of_battery_sizes

body:
You have a 1V drop from about 5V or a 25% load regulation error you know that you have excessive load and for active servos this is a result of the DC coil resistance of the motors that are active.

- If you knew the motor coil resistance then for a transient servo seek, the surge voltage drop can be predicted from the ratio of the load to total resistance (Load+Rs of batteries)
- the main Rule of Thumb to learn is the series resistance adds with batteries in series and reduces with batteries in parallel and thus larger capacity. So you expect the product or Rs and Ah to be constant within some family of same chemistry and brand name.

But there may be sources of deviations to test results so the method must be specified or the same to compare.

- the Rs of batteries rises sharply as state of charge SoC drops below 10%  and gradually with repeated sweep tests but lowers gradually with rising temperature.

Let's compare different brands of NiMH (AA vs C) and see how close this is.  You can try your own plots to measure the slope of bulk resistance from the VI plots  ΔV / ΔI = Rs [Ω]

 1. https://eneloop101.com/batteries/eneloop-test-results/
 2. https://lygte-info.dk/review/batteries2012/Enesense C 4300mAh (White) UK.html
 3. http://lygte-info.dk/review/batteries2012/Eneloop AA BK-3MCCE 1900mAh (White) UK.html

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

This means changing these products from AA to C results in 31% Rs which equates to a voltage drop and 226% of the AA's Ah capacity.

Eneloop is known to be a reliable high-performance NiMH brand.
Your batteries may have less performance.  You can measure your motor resistance and see if upgrading size or quality and/or cost of batteries to get the performance you need.

The LED fluctuation is a different problem from not using a constant current driver.

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

body: Welcome! You picked a good place to connect the batteries when fully charged but it is the wrong place. You can use the Vin pin to Power your Arduino with an regulated or unregulated 7 to 12-volt power source. Like several AA batteries in series or a wall adapter that is in the range of 7 to 12 volts. Alternatively, you can power your Arduino through the 5V pin with an external regulated 5V power supply. Leave the 9V batteries for the smoke detectors they do not work very well.


body:
On day to day basis I'm more of a high level programmer, with little electronics knowledge, apologies in advance if I lack some nomenclature or basics. I communicate with my Arduino Mega via firmata, so won't really bother with code as I believe my issue is 100% hardware issue (if proven wrong I'll share details surely)

I'm creating a 'keyboard' with 60 arcade style push buttons (2pin), and I distinguish them by different resistance when circuit closes with A0-A9 (10 analog pins, 6 buttons each), and I need the rest of the pins for other functionalities.

I've created a circuit similar to this fritzting schema:
[![enter image description here][1]][1]

So my issue is: when press button A0/button 1, pins A1 & A2 also read the same value. If I press A0/button 2, I get a different value and can determine which button in A0 was pressed, but again - A1 & A2 also read this, even though I didn't press them.

I suspect I might've taken a different approach or even out of the box "keyboard" chips, but this is the route I've taken.

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

How do I make it so when I press A0/button 1, A1/A2 doesn't read the value? Do I need separate V5? Or I simply need to put the wires differently somehow?

Update: as per **chrisl** comment

I've updated the circuit by adding a resistor for each button group:

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

And that has solved my issue.

  [1]: https://i.stack.imgur.com/2p9W2.jpg
  [2]: https://i.stack.imgur.com/5i4SO.jpg
  [3]: https://i.stack.imgur.com/iYPke.jpg

title: Arduino Mega, 6 push buttons for each analog input (A0-A9) - closing one results in reading by other

Answers: 1

body:
Of course all three analog inputs show the same value. You have literally connected them to each other. Each green wire is connected to a red wire, which leads to the resistor at the bottom. Thus all three inputs are tied together.

You can fix this by using one bottom resistor for each group of 2 buttons, each connected between 5V and the analog input/button system.

And when using analog inputs for multiple buttons the binary resistor latter is an interesting concept, which might give you more buttons per analog input (depending on the noise in your environment). Though the typical way to read so many buttons would be using an additional chip/microcontroller to scan the buttons in a matrix style arrangement. With your current circuit you still need 30 analog inputs.


body:
So I am trying to power an arduino to measure water flow. It works all fine and dandy when I am powering it with laptop, but when I directly power it with 12V 1.5A adaptor the readings take a second to come to the LCD even though the pump starts running. Also when they come, I can see that sometimes it hangs. Why is that?

Before taking the readings I am switching on a motor which is also directly powered by the adaptor just like the arduino.

Below is a block diagram.

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

Would adding a voltage regulator that steps down 12V to 9v between arduino and adaptor help?

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

title: Lag in sensor reading when Arduino Powered with 12V adaptor

Answers: 2

body:
Your power supply is actually advertised at 1.2 Amps.  It's assumed you are powering the Arduino, the Relay, the Water Valve Solenoid and the Water-Pump-Motor all w/the same 1.2A power supply.  It is within reason that the sum of all those loads exceeds your power supply's capabilities.

> It works all fine and dandy when I am powering it with laptop ...

It is assumed you were only powering the Arduino with the laptop.  Providing the Arudino with an independent power source is a common solution to this type of problem.  Obtaining a larger power supply (more Amps) is another possible solution.

Why does it eventually work?

Motors require more Amps when under a physical load.  If the water is stationary, the motor will have to "get it moving" requiring more current. The term "locked motor current" is used [here in this article][1].

Also, inductor loads require more Amps when ever the voltage potential is suddenly changed.  The motor and relay are likely both seen as inductive loads.  This is referred to as [inrush current][2].

Both of these can be assumed transitory.  Once the motor is moving and after the potential across the inductive loads are closer to zero, the initial current demand will subside and the power supply may then be capable of sustaining the constant voltage needed by the Arduino's processor.

Alternate solution:

Obtaining a larger power supply is likely the better solution.  Another option involves filtering the power only for the Arduino.  This option is discussed [in this thread][3] on forum.arduino.cc where a diode and capacitor are used to somewhat isolate the power for the motor, relay and solenoid from the Arduino.

  [1]: https://www.jadelearning.com/blog/understanding-motor-starting-inrush-currents-nec-article-430-52/
  [2]: https://www.sunpower-uk.com/glossary/what-is-inrush-current/
  [3]: https://forum.arduino.cc/t/noise-filter-for-uno-power-supply/228542

body: Welcome. Your pump is turning on as soon as the power is turned on because the relay is connected to 5V. Your processor needs to initialize itself and then the display, the pump is up and running. On your laptop the pump was powered from the power supply and the Arduino by the laptop. The arduino was on and up and running when the pump was started. Hope this helps. I will take a SWAG and say this is powered up when the pump is needed and powered down when it is not needed.


body: I want to place all of my libraries on the server. Currently the sketches work fine and as far as I know the libraries are coming from the individual linux mint machines using cinnamon, releases vary depending on machine. I can move the libraries etc but what do I do to the IDE 1.8.18 and 1.8.19? to make it follow that path.

title: Library files multiple users

Answers: 1

body:
Arduino IDE can use libraries only from 3 locations.

1) libraries folder in sketchbook folder
2) libraries folder of selected board's platform
3) libraries folder in IDE installation folder (only IDE 1, not IDE 2)

There is no option to configure other paths and absolute or relative paths don't work in `#include` directive with the Arduino build process.

The only way to use libraries from a different location is to link with means of the operating system the folder with the library into one of the searched locations.


body:
I am trying to use a cert with an ESP8266 the identical code works fine on ESP32 but for the ESP8266 I am getting errors.

I set the cert as follows

```
const char *ROOT_CERT PROGMEM = R"EOF(= "-----BEGIN CERTIFICATE-----
MIIFYDCCBEigAwIBAgIQQAF3ITfU6UK47naqPGQKtzANBgkqhkiG9w0BAQsFADA/
MSQwIgYDVQQKExtEaWdpdGFsIFNpZ25hdHVyZSBUcnVzdCBDby4xFzAVBgNVBAMT
...
-----END CERTIFICATE--------)EOF";
```
For the ESP32 I use

```
wifiClient.setCACert(ROOT_CERT)
```
Which works fine but on the 8266 I get.

```
no matching function for call to 'BearSSL::WiFiClientSecure::setCACert(const char*&)'
```
I have done some research and there is some suggestions the length is required so I tried that also

```
 wifiClient.setCACert(ROOT_CERT,sizeof(ROOT_CERT)-1);
```
But that produces the following error.

```
invalid conversion from 'const char*' to 'const uint8_t* {aka const unsigned char*}' [-fpermissive]
```
I am using the 2.7.4 8266 board library as I have heard the 3.X has similar issues.

I have tried V 3.X but I get the following
```
class BearSSL::WiFiClientSecure' has no member named 'setCACert'
```

title: Coorect syntax for setCACert ESP8266

Answers: 1

body:
i could not use setCACert with 8266.  you need to do it differently and i had to do some web hunting.
But finally i did get my telegram test working from esp32 to 8266,
 here is what i did and hope that you can adapt it

you need :

    #include <ESP8266WiFi.h>

after your defines add:

    X509List cert(TELEGRAM_CERTIFICATE_ROOT);
    WiFiClientSecure client;
    UniversalTelegramBot bot(BOTtokenValue,client);

in setup i had to add BOTH of these lines (i initially didnt think i needed the 1st line, but apparently you do) :

    configTime(0, 0, "pool.ntp.org");   // get UTC time via NTP
    client.setTrustAnchors(&cert);      // Add root certificate for api.telegram.org

this got my ESP32 code converted from ESP32 to 8266


body:
I just got myself a STM32F103C8 Blue pill board. I am having funny behaviour with the analog readings. It behaves as if the unit was 10bits and not 12 bits.

I uploaded the very trivial Arduino code below. Just to read the analog input A0.

    void setup() {
      Serial.begin(38400);
    }
    void loop() {
      Serial.println(analogRead(A0));
      delay(1000);
    }

If I connect pin A0 to the 3.3v I get this output below.

    1022
    1022
    1023
    1022
    1022
    etc...

If I connect to a 1.5V source the above values becomes around 500.

It all behaves as if it was 10bits really which I fail to understand. Any ideas why?

title: Blue pill acting as if it had 10bit ADC

Answers: 2

body:
If you run Arduino code on it, maybe it makes sense to have 10-bit ADC readings on this platform too like on all other Arduino platforms. Unless you configure the libraries to return full 12 bit, if even possible.

This is more an Arduino platform question though.

body:
Adding the following line in the setup() section solves the problem.

    analogReadResolution(12)


body:
I want to create an AC PWM pulse with arduino. The microcontoller, will be also responsible for specifying the frequency (which will be around 500 Hz).

External electronic components can also be used. Like an H-Bridge perhaps.

EDIT: This is the final waveform I want to produce:
[![enter image description here][1]][1]

I know the arduino is not capable of producing 36 V output. I plan to just create this waveform, with whatever the arduino can output  and then step up the voltage. But this is the final waveform that I want produced.

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

title: Creating an AC pulse with arduino and perhaps components

Answers: 1

body:
Yes, you want a H-bridge. That is the simplest way to make that "negative*" voltage.

But you can't just create a square wave and throw it blindly at a H-bridge, you have to be much more careful, otherwise you will cause short circuits and dissipate massive amounts of power.

You will need a "discrete" H-bridge where you have proper control over each transistor, and the best way of doing that is with discrete transistors (MOSFETs are best).

The important thing to remember though is than no transistor ever turns off or on instantaneously - so you have to add a "dead zone" into your waveform.  Turn one pair of MOSFETs off, then wait a moment, before turning the other pair on. Otherwise you get a brief overlap in the switching where massive currents can flow straight through everything as all the MOSFETs are turned on (or partially on) at the same time.

Some microcontrollers have programmable dead zones in their PWM outputs, but I am not sure if the AVR chips do - you'll have to check the datasheet - but it's not too hard to arrange a suitable waveform in software or using timers and interrupts (you could look at the `tone()` function and support code for some ideas for the latter).

The programming sequence, if you have 4 outputs H1/H2/L1/L2 for the HIGH and LOW sides of the H bridge pairs 1 and 2, would be:

1. Turn on H1 and L2
2. Pause
3. Turn off H1 and L2
4. Brief Pause
5. Turn on H2 and L1
6. Pause
7. Turn off H2 and L1
8. Brief Pause
9. Repeat

You haven't specified what your load is, but with an H-bridge it is important to remember that the output is not referenced directly to ground but ground alternates from side to side. If you want to properly isolate it from the Arduino ground a transformer can be used as the load to the H-bridge then use the output of the transformer to drive your real load. You can also use the transformer to change the output voltage (the ratio of windings is the same as the ratio of input to output voltage - so a 1:1 winding transformer will give the same voltage out as it gets in).

----
* "Negative" only that the current flows the opposite way through the load, not an actual negative voltage WRT to Arduino GND.


body:
I have a 32.768 kHz signal at the ATmega328P input.
I need to get 2 signals from this signal: 1Hz and 32Hz.
How well will it work?
How to do this with a ATmega328P Timer/Counter?
What gain will the Timer/Counter give compared to my solution?

    void setup() {
       pinMode(S32768Hz_PIN, INPUT_PULLUP); // 32.768 kHz signal
       attachInterrupt(digitalPinToInterrupt(S32768Hz_PIN), s32768Isr, FALLING); // Pin 3
    }

    volatile bool s32768IsrWasCalled = false;  // ISR flag 32768Hz
    void s32768Isr() {
       s32768IsrWasCalled = true;
    }
    uint16_t s32Counter = 0;
    uint16_t s1Counter = 0;

    void loop() {
      if (s32768IsrWasCalled) {
          s32768IsrWasCalled = false;
          s32Counter++;
          if (s32Counter == 1024) {
            s32Counter = 0;
            // 32Hz
          }

          s1Counter++;
          if (s1Counter == 32768) {
            s1Counter = 0;
            // 1Hz
          }
      }
    }

Update 24.10.2022
I wrote my first timer 1 setup code. Will this run 32 times per second, indefinitely?

    // ATmega328P 3.3V 8MHz, Timer 1 & DS3231 32768 Hz
    void setupTimer1() {
        // Disables all interrupts
        cli();
        // Reset bits
        TCCR1A = 0;
        TCCR1B = 0;
        // Enable Timer 1 overflow interrupt (TOIE1)
        TIMSK1 = (1 << TOIE1);
        // PWM mode. Mode #7 (fast PWM, top is fixed at 10 bits = 1024)
        TCCR1A |= _BV(WGM10) | _BV(WGM11);
        TCCR1B |= _BV(WGM12);
        // External clock on T1 pin, on falling edge (DS3231 32768Hz pin)
        TCCR1B |= (1 << CS11) | (1 << CS12);
        // Enables interrupts
        sei();
        // pinMode(T1_pin, INPUT_PULLUP); ?
    }

    void loop() {
        // So get 1 Hz from 32 Hz?
        // There will be no data races here?
        if((pulse_counter % 32) == 0) {
            callback1Hz();
        }

        if((pulse_counter % 2) == 0) {
            callback16Hz();
        }
    }

    volatile uint8_t pulse_counter;
    // Timer 1 Overflow (32 Hz)
    ISR(TIMER1_OVF_vect) {
        pulse_counter++;
    }

Thank you!

title: 1Hz & 32Hz from 32.768 kHz on ATmega328P at 8MHz & DS3231 32K

Answers: 1

body:
I did not test your program but, just by looking at it, I would expect
it to work... provided you do not add more code! Obviously you will need
to add more code in order to do something useful with those signals, and
then thinks might break.

The problem with this approach is that the interrupt rate is pretty
high: the program gets interrupted every 30.5 µs. You may miss an
interrupt if either:

 1. it fires while there is already an interrupt (or other critical
    section) being processed, and that interrupt (maybe combined with
    some other pending interrupt) takes more than 30.5 µs to
    complete

 2. you add more code to `loop()` and that function ends up taking more
    than 30.5 µs.

The first condition should be obvious, but I would assume the risk is
quite low, as only a very poorly written ISR would take that long to
complete. Beware however of library code, as that might bring surprises.

The second condition is a bigger risk, although maybe less obvious. The
problem is that this `loop()` assumes the code within
`if (s32768IsrWasCalled)` is going to be called exactly once per
interrupt. This may not be the case: if the program gets bigger, you may
miss interrupts, and get the frequencies wrong.

A simple way to avoid the issue number 2 is to count the pulses within
the ISR, as PMF suggests in a comment. I would use a single counter for
this, and make it unsigned in order to guarantee that it wraps around
reliably:

```c++
volatile uint16_t pulse_counter;
void s32768Isr() {
    pulse_counter++;
}

void loop() {
    int signal_32Hz = (pulse_counter >> 9) & 1;
    int signal_1Hz = (pulse_counter >> 14) & 1;
}
```

Note that this is one of the few cases when you can access the volatile
multi-byte variable without disabling interrupts: since you only ever
care about one bit, there is no data race.

A better option, though, would be to use a hardware timer for this job.
I would suggest using Timer 1 in “counter” mode (external clock
source on pin T1). Using mode 7 (fast PWM, 10-bit) you get the
32 Hz signal entirely generated by the hardware. And then you can
use the timer overflow interrupt to generate 1 Hz. The interrupt
rate is now 1024 times lower. I let you check the datasheet for the
details.