text:
Converting 16bit to float
I am trying to communicate with AT30TS75A-MA8M-T with below code, the problem is converting the 16 bit output to float so I can read temp:
Base on data sheet

I suppose to remove first 5 bit in order to read correctly but I am not converting it correctly.
Ex: (0b001001001100000 AND 0 b0111111111100000) = 0b1001001100000
0b1001001100000 >> 5 = 0b10010011 = 147
    void Atemp::begin()
{

    Wire.begin();

    // Check if sensor temp sensor is avilable

    // if (mySensor.beginI2C() == false)
    // {
    //     data[9] = 5; // Error Code
    // }
    // Set registor for two decimal
    Wire.beginTransmission(_i2cAddress);
    Wire.write(1);
    Wire.write(0b01100000);
    Wire.endTransmission();
}

void Atemp::read()
{
    Wire.beginTransmission(_i2cAddress);
    Wire.write(0);
    result = Wire.endTransmission();
    // result is 0-4
    if (result != 0)
    {
        data[9] = 5; // Error Code
    }

    result = Wire.requestFrom(_i2cAddress, (uint8_t)2);
    if (result != 2)
    {
        data[9] = 5; // Error Code
    }
    else
    {
        uint8_t part1 = Wire.read();
        uint8_t part2 = Wire.read();

        data[7] = part1;
         data[8] = part2;
        int16_t rawval = (part1 << 8 | part2) ;
        // rawval >>= 6;
        float temp = rawval / 256.0f;
        floatconv(temp);
    }
}

You need to do two things:

Right-shift the data to align it to the right of the variable, and
Multiply it by the value of one bit.

When right shifting be sure to do it in a signed data type so that C will sign extend the value and retain any negativeness to the value.
So taking the 12-bit examples from the datasheet you right shift 4 bits, so
SDDDDDDDDDDD0000

becomes
SSSSSDDDDDDDDDDD

(where S is the sign bit and D is a valid data bit, and 0 is padding)
Then simply multiply the value by 0.0625 to get the actual temperature.
In code that might look like:
int16_t rawval = part1 << 8 | part2;
rawval >>= 4; // Do this in the int16_t to preserve the sign
float temperature = rawval * 0.0625;

For different resolutions right shift by different amounts and multiply by the appropriate single-bit value for that resolution (hint: 11 bit is double the value of 12 bit, 10 bit is double the value of 11 bit, etc).

@Shahreza Page 10 of the datasheet. The resolution of the temperature measurement data can be configured to 9, 10, 11, or 12 bits which corresponds to temperature increments of 0.5̊C, 0.25̊C, 0.125̊C, and 0.0625̊C, respectively.

Just a complement to Majenko's answer. The temperature register is set
in such a way that you can interpret it in the same way irrespective of
the selected resolution:
int16_t rawval = part1 << 8 | part2;
float temperature = rawval * (1/256.0);

Good plan - didn't think of that ;)


text:
ESP32- Sporadic slow receive of MQTT messages
Problem description: Every ~20+ published messages (using terminal), MCU receives that message in a very noticeable delay (mostly ~10 sec, few time it got up to 1 min). Upon receive (printed in Serial monitor), MCU is working as expected.
Hardware: ESP32 DEVKIT MCU, PubSubClient.h for MQTT and WiFi.h for WiFi.
Important remark: Code is same for ESP8266 and ESP32.This behavior happens only on ESP32.
Question: Does ESP32 has a know issue regarding receiving MQTT messages? is there a workaround? or perhaps- bug in code?
What did I do to try isolating the problem:

Tried on 3 different ESP32s (2 DEVkit MCU, and 1 with relays on board) - same behavior - it is not an specific MCU hardware problem.

Used another PC to publish MQTT messages (via terminal. MAC and Linux, and a 3rd party MQTT App)- no change. It has nothing to do with publishing platform.

To rule out it may be a MQTT broker's fault (Local RPI3 connected using LAN cable)- Subscribing to that topic in order to see if the delay repeats . MQTT server receive pubs on time. Broker responds on time (while waiting to see when publish is received in Serial monitor).

adding a flashing LED every 200ms in loop(), to verify that MCU is not get stuck in a process. loop() is looping as expected (see in code below).

Spitting heap free memory to Serial monitor, in order to see if there is some memory issue, degradation. Nothing suspicious.

Code simplification- used code segments from ESP32 wifi and MQTT pubsub's example, while disabling every functionality of original code(with and without). Delay still happens sporadically.

OUTPUT1- sending "0" and "1" almost simultaneously,  almost 15 sec delay
13:31:21.516 -> Message arrived [myHome/test] 0 <--- right after this, "1" was sent
13:31:22.510 -> 278616 <---- free heap size (send every 1000 ms. non-blocking)
13:31:23.570 -> 278616
13:31:24.630 -> 278616
13:31:25.657 -> 278616
13:31:26.718 -> 278616
13:31:27.778 -> 278616
13:31:28.805 -> 278616
13:31:29.866 -> 278616
13:31:30.926 -> 278616
13:31:31.954 -> 278616
13:31:33.014 -> 278616
13:31:34.075 -> 278616
13:31:35.102 -> 278616
13:31:35.964 -> Message arrived [myHome/test] 1 <--- received 15 sec later

OUTPUT-2: Code
#include <WiFi.h>
#include <PubSubClient.h>

WiFiClient espClient;
PubSubClient client(espClient);

const char *mqtt_server = "192.168.2.100";

void setup_wifi()
{

        delay(10);
        // We start by connecting to a WiFi network
        Serial.println();
        Serial.print("Connecting to ");
        // Serial.println(ssid);

        WiFi.mode(WIFI_STA);
        WiFi.begin("iot", "GdS");

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

        Serial.println("");
        Serial.println("WiFi connected");
        Serial.println("IP address: ");
        Serial.println(WiFi.localIP());
}

void callback(char *topic, byte *payload, unsigned int length)
{
        Serial.print("Message arrived [");
        Serial.print(topic);
        Serial.print("] ");
        for (int i = 0; i < length; i++)
        {
                Serial.print((char)payload[i]);
        }
        Serial.println();

        // Switch on the LED if an 1 was received as first character
}

void reconnect()
{
        // Loop until we're reconnected
        while (!client.connected())
        {
                Serial.print("Attempting MQTT connection...");
                // Create a random client ID
                String clientId = "ESP8266Client-";
                clientId += String(random(0xffff), HEX);
                // Attempt to connect
                if (client.connect(clientId.c_str()),"guy","kupelu9e")
                {
                        Serial.println("connected");
                        // Once connected, publish an announcement...
                        client.publish("myHome/log", "hello world");
                        // ... and resubscribe
                        client.subscribe("myHome/test");
                }
                else
                {
                        Serial.print("failed, rc=");
                        Serial.print(client.state());
                        Serial.println(" try again in 5 seconds");
                        // Wait 5 seconds before retrying
                        delay(5000);
                }
        }
}

void setup()
{
        Serial.begin(115200);
        setup_wifi();
        client.setServer(mqtt_server, 1883);
        client.setCallback(callback);
        reconnect();
}
void loop()
{
        loop_buttons();
        if (!client.connected())
        {
                reconnect();
        }
        client.loop();
        static unsigned long lastentry = 0;
        static unsigned long lastentry2 = 0;
        if (millis() - lastentry > 200)
        {
                pinMode(2, OUTPUT);
                digitalWrite(2, !digitalRead(2));
                lastentry = millis();
        }
        delay(50);
        if (millis() - lastentry2 > 1000)
        {
                Serial.println(ESP.getFreeHeap());
                lastentry2 = millis();
        }
}

The code you posted does not compile as there is no loop_buttons().

@StarCat You are right. It is a left over. Please comment it out.

guyd, did the answer help?

I have a very similar problem - but I use ESP8266 (observe it on different types - NodeMCU, ESP-01S etc).  I cleaned up  MQTT callback - no use of Serial there (tried to follow what was suggested by Accomation below) - no success.

In case somebody finds this when faced with the same issue:
I had a similar problem on a Pico W. Turned out that the Serial.println()s in the MQTT callback clobbered the MQTT+WiFi stack. Something did not multitask nicely. Not accessing the Arduino Serial port in the MQTT callback fixed it.

source: Stack Exchange

license: Creative Commons - Attribution Share-Alike - https://creativecommons.org/licenses/by-sa/4.0/

sort: votes


text:
No GPS data Neo 6M DFRduino Nano
I checked several answers for same question but none of them help.
I also changed the nano board and GPS module but without luck. I ran it outdoor.
This post question had same issue except my date does not display the correct date and time.
My connection:
vcc->5V
rxd->d4
txd->d3
gnd->gnd

FullExample program from TinyGPS++, I get following types of entries
Sats HDOP  Latitude   Longitude   Fix  Date       Time     Date Alt    Course Speed Card  Distance Course Card  Chars Sentences Checksum
           (deg)      (deg)       Age                      Age  (m)    --- from GPS ----  ---- to London  ----  RX    RX        Fail
----------------------------------------------------------------------------------------------------------------------------------------
0    100.0  ********** *********** **** 00/00/2000 00:00:00 152  ****** ****** ***** ***   ******** ****** ***   324   0         0
0    100.0  ********** *********** **** 00/00/2000 00:00:00 230  ****** ****** ***** ***   ******** ****** ***   486   0         0
0    100.0  ********** *********** **** 00/00/2000 00:00:00 308  ****** ****** ***** ***   ******** ****** ***   648   0         0
0    100.0  ********** *********** **** 00/00/2000 00:00:00 384  ****** ****** ***** ***   ******** ****** ***   810   0         0
0    100.0  ********** *********** **** 00/00/2000 00:00:00 463  ****** ****** ***** ***   ******** ****** ***   972   0         0
0    100.0  ********** *********** **** 00/00/2000 00:00:00 541  ****** ****** ***** ***   ******** ****** ***   1134  0         0

NMEA read from serial
$GPGGA,,,,,,0,00,99.99,,,,,,*48
$GPGSA,A,1,,,,,,,,,,,,,99.99,99.99,99.99*30
$GPGSV,1,1,01,05,,,20*7F
$GPGLL,,,,,,V,N*64
$GPRMC,,V,,,,,,,,,,N*53
$GPVTG,,,,,,,,,N*30

$GPGGA,,,,,,0,00,99.99,,,,,,*48
$GPGSA,A,1,,,,,,,,,,,,,99.99,99.99,99.99*30
$GPGSV,1,1,01,14,,,29*76
$GPGLL,,,,,,V,N*64
$GPRMC,,V,,,,,,,,,,N*53
$GPVTG,,,,,,,,,N*30

UPDATE:
I change the antenna. At some time I got this. From the GPGSV sentence I know that there are about 15 16 satellites in view but the FullExample only show 0.
$GPRMC,,V,,,,,,,,,,N*53
$GPVTG,,,,,,,,,N*30
$GPGGA,,,,,,0,00,99.99,,,,,,*48
$GPGSA,A,1,,,,,,,,,,,,,99.99,99.99,99.99*30
$GPGSV,4,1,15,04,,,31,07,,,33,09,,,34,11,,,30*74
$GPGSV,4,2,15,12,,,33,13,,,30,14,,,33,15,,,27*7D
$GPGSV,4,3,15,16,,,33,19,,,34,20,,,30,21,,,33*70
$GPGSV,4,4,15,22,,,32,23,,,33,33,,,35*7B
$GPGLL,,,,,,V,N*64

$GPRMC,,V,,,,,,,,,,N*53
$GPVTG,,,,,,,,,N*30
$GPGGA,,,,,,0,00,99.99,,,,,,*48
$GPGSA,A,1,,,,,,,,,,,,,99.99,99.99,99.99*30
$GPGSV,4,1,16,04,,,32,07,,,33,08,,,31,09,,,33*7A
$GPGSV,4,2,16,11,,,29,12,,,33,13,,,30,14,,,34*73
$GPGSV,4,3,16,15,,,32,16,,,33,19,,,33,20,,,31*73
$GPGSV,4,4,16,21,,,33,22,,,33,23,,,34,33,,,35*7D
$GPGLL,,,,,,V,N*64

My idea now is to supply external power for the DFRduino Nano
Any idea how I can continue. Should I changed to other type of gps module?

"I ran it outdoor" Under a clear sky and for some number of minutes, right?

@timemage yes. From this post, it takes 1 or 2 hours to charge EEPROM and the onboard RTC. Without RTC syc time, it cannot get correct date time in my case

You just have made some interpretation with with my name. I wasn't asking about time/RTC output at all. Only that you had it where we could be certain that you would get a fix at the end of so many minutes if everything were correct. So many avoid this. With your update it seems whatever software is involved is correct so far as it goes. Check your antenna connections, that nothing (including the Arduino) near is injecting interference, and try powering it from different sources.

@timemage With 5V power supply from Nano I got the module damaged (Rx Tx get shorten), do you have any idea?

A short has nothing to do with the problem here. Besides that shortening RX and TX doesn't damage anything (unless you connect two TX pins)

If I had to guess you're referring to getting the directions incorrect when trying to use a Nano as only a transceiver. The Nano's RX and TX are labeled from the perspective of the AVR and are 5V (most GPS are 3.3V). The 1K series resistors on the Nano's RX/TX limit the trouble you can get into here if the AVR was in reset. But I don't really understand what you're saying. You should edit any new information directly into the question.

@timemage I connected as mention above. For a while ( 5 6 hours running) the RX TX do not working any more. They got shorten. From this forum, power supply for NEO 6M should typically be 3.0V and range: 2.7V to 3.6V while I supplied 5V

Glad you got it working. I dunno that I've heard someone use "short" in the way that you are.

The ceramic antenna is the issue. I changed to the external 1.5GHz one. It got fix under 5 seconds

all_licenses: Creative Commons - Attribution Share-Alike - https://creativecommons.org/licenses/by-sa/4.0/


text:
Can you coax another I²C connection out of an Arduino Nano Every?
I'm looking to network a bunch of devices (boards in a Eurorack case) over I²C, but I don't want to compromise the address space available to each individual device for its own needs. The obvious solution here is to give each device its own I²C bus which it controls, and then connect them together over another.
Two independent I²C connections would be needed on a microcontroller in this setup, and if I understand the datasheet correctly, the MCU on the Arduino Nano Every can act as host on one bus and client on another using the Dual Mode setup of the Two-Wire Interface (see Chapter 25 of the linked datasheet), but the board only exposes two sets of I²C-capable pins and they are wired together in the schematic.
What steps would I need to take to coax another I²C connection out of an Arduino Nano Every?

ATmega4809 only has one hardware i2c interface. If you need a second i2C, you can use any GPIO pins as i2c pins and create software i2C (bit-banging) yourself, or find some software i2c library online. You can also buy i2c expander/extender as a hardware solution.

If that's the case, what exactly is the dual mode for? The host and client capabilities patently cannot use the same bus independently, as I²C is only half-duplex, so if what you say is true the datasheet seems to be misrepresenting the 4809's TWI.

If you're asking about hardware supported I2C/TWI, then you seem to have answered your own question. So, you could post an answer that says "No, not without modifying the board." For what it's worth, I don't understand the devices involved and the topology and direction of data flow well enough to know that modifying the board would ultimately help you anyway. Same for using an I2C multiplexer.

ATmega4809 datasheet does not misrepresenting the TWI. Dual mode does not mean two TWI ports, it means that you can have two set of TWI wires, one for master and one for slave, internally it controlled by setting the registers, you can think as there are two STDP switches controlled by the PORTMUX register that switch between master and slave wires. Read "15 PORTMUX" and "25. TWI - Two-Wire Interface" of the datasheet to understand the dual-mode TWI.

Welcome!
Theoretically you can connect 127 devices to the I2C bus. I suggest you do a little reading on the I2C bus before you start your design. Hopefully all of these I2C devices are on the same board but since you want to network them I have a feeling you are making a very painful mistake. I2C was never intended to be used for networking.
For a bunch of devices I would seriously look at CAN, two wires to connect them is all that is needed even for well over 250 meters or 800 feet with the baud rate of 250 kbit/s. I usually also run a ground. This will be much faster than the I2C. CAN is a simplex communication mode that turns around very fast. Each node can send and receive under software control. It does its own arbitration no need to worry about it the controllers do it for you.

I considered CAN, but I thought it a little overengineered for what I'm trying to achieve. I've clarified the question, as I didn't make it clear that the length scale is shorter than the verb "network" would suggest.

You will probably have to shield the I2C bus as that many on an audio mixer will create noise. You may also have to slow it down because of bus capacitance. Let us know how you do.


text:
Can I run Arduino code on a 6502?
I've been doing projects with the arduino boards for a long time and accordingly also with the libs from adafruit etc. But that was too boring for me and I wanted to get more into the matter, so I used youtube and acquired knowledge about the microcontrollers eeproms etc. itself . But now my question is whether I, if I have the necessary interface adapters, etc., can compile the libs from adafruit, etc. and flash the hex file directly onto an eeprom and then use it with e.g. connect and use a 6502. but I need the corresponding settings in the IDE so that the code can be executed correctly, right? and what is the best way to do this? and general tips would also be nice thanks in advance

Perhaps the results of a search for "6502 vs avr" would be enlightening.

your question is same as can I speak Swahili to an Englishman and be clearly understood?

Maybe yes on a C++ level but you have to write the tool chain and all the needed files. That would including all the libraries you use. In about 20 years you may have enough done to start testing.  As far as flasining, if my memory is correct it has no RAM or FLASH so you will also have to design the chip.

No, you can't.
You would fail at the first hurdle: you would need to find a 6502 C++ compiler, and AFAICT there is no such thing.
Without a C++ compiler for the 6502 you would never be able to compile C++ code for the 6502.
The closest you would come is to program in pure C for the 6502, which means you won't be able to use 99% of the Arduino libraries (not counting the fact that many use architecture-specific register access) since they are written in C++ not in C.


text:
Input on the Nano RP2040 does not float
I am using the Nano RP2040 with MicroPython and run the following code:
import machine
import time

p0 = machine.Pin(0, machine.Pin.IN)
while True:
    print(p0.value())
    time.sleep(0.3)

The Nano has built-in pull-up and pull-down resistors. If I do not specify machine.Pin.PULL_xx, then these built-in resistors are not activated. If they are not activated, then shouldn't the signal received be floating, i.e., shouldn't the environment interfere with the input signal and make the code above print random series of 0s and 1s on the REPL? What actually happens is the REPL prints all 0s.
I read of how input pins are interpreted as high-impedance output and while I suspect this may be the cause, I do not not understand what that means.

is the input pin connected to anything? ... what happens if you touch the pin?

That you'll get noise on a floating input observable in the read value isn't something you can rely on. The AVR like the ATMega328P seems to readily couple house/mains frequency noise onto inputs. However, I went to demonstrate this sort of thing for someone with a NodeMCU(ESP8266) board and found it was much harder to influence.
As I understand it the RP2040 has configurable Schmitt trigger inputs with a minimum hysteresis of 0.1 * IOVDD, 330 mV minimum, I think. And that these are on by default.  So your noise has to be bouncing across this threshold to affect the read value, which it may easily not be doing. If you turn off the Schmitt trigger feature, you may see more noise. I don't know how to disable them in MicroPython. The PicoSDK has a function called gpio_set_input_hysteresis_enabled that should do it.
You can also try running something like an old vacuum cleaner next to it to throw lots of noise into the environment.
For my own curiosity I may try playing with this on an RPI Pico, though perhaps not in MicroPython (we'll see) and if I do I'll show what I found.


text:
Using Millis instead of delay to reboot relay
I want to reboot relay (turn off , waiting 4 seconds and turn ON)
it works perfectly if I use delay(4000), but code is blocked while delay (4 seconds) and I cant start relay 2.
How can I use Millis instead of delay to reboot relay 1 and start relay 2 same time?
#include <SPI.h>
#include <Ethernet.h>
#include <Wire.h>
#include <EthernetUdp.h> //Load the Udp Library

//Ethernet
byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED}; //Assign mac address
IPAddress ip(192, 168, 1, 178); //Assign the IP Adress
unsigned int localPort = 80; // Assign a port to talk over
char packetBuffer[UDP_TX_PACKET_MAX_SIZE]; //dimensian a char array to hold our data packet
String datReq; //String for our data
int packetSize; //Size of the packet
EthernetUDP Udp; // Create a UDP Object                            //server port
String readString;

bool relayState = false;
//define relay pins
int relay_1 = 22;
int relay_2 = 24;

void setup() {
  Serial.begin(9600);
  Ethernet.begin(mac, ip);
  Udp.begin(localPort); //Initialize Udp
  delay(2000);

  //Initial state of the relay
  pinMode(relay_1, OUTPUT); digitalWrite(relay_1, LOW); //relay 1 is On
  pinMode(relay_2, OUTPUT); digitalWrite(relay_2, HIGH);//relay 2 is Off

}

void loop() {

  packetSize = Udp.parsePacket(); //Reads the packet size
  if (packetSize > 0) { //if packetSize is >0, that means someone has sent a request
    Udp.read(packetBuffer, UDP_TX_PACKET_MAX_SIZE); //Read the data request
    String datReq(packetBuffer); //Convert char array packetBuffer into a string called datReq
    //Serial.println(datReq);

    if (datReq == "relay1reboot") { //reboot relay
      digitalWrite(relay_1, HIGH);//relay off
      delay(4000);
      digitalWrite(relay_1, LOW);//relay on

      Udp.beginPacket(Udp.remoteIP(), Udp.remotePort()); //Initialize packet send
      Udp.print("relay 1 reboot");
      Udp.endPacket(); //End the packet

    }
    if (datReq == "relay2on") {
      digitalWrite(relay_2, LOW);//relay 2 on
      Udp.beginPacket(Udp.remoteIP(), Udp.remotePort()); //Initialize packet send
      Udp.print("relay 2 on");
      Udp.endPacket(); //End the packet
    }
    if (datReq == "relay1on") {
      digitalWrite(relay_1, LOW);//relay 2 on
      Udp.beginPacket(Udp.remoteIP(), Udp.remotePort()); //Initialize packet send
      Udp.print("relay 1 on");
      Udp.endPacket(); //End the packet
    }
    // Use the snapshot to set track time until next event
    //previousMillis = currentMillis;
  }
}

//}
memset(packetBuffer, 0, UDP_TX_PACKET_MAX_SIZE); //clear out the packetBuffer array

}

reboot is a term that is specific to programmable devices, such as computers ... it does not apply to a simple relay ... it would make sense to say I want to cycle a relay

A general approach to remove a delay() is to replace it by some code
that:

takes note that some action (whatever follows the delay()) will have
to be performed in the future

takes note of the current time.

Then, somewhere else in loop(), you check whether that “some action”
has to be done right now and, if this is the case, does it.
In this particular case, I would add a global boolean variable named
relay1isRebooting. When it is true, that means that the relay has been
turned off and will have to be turned on in the near future.
bool relay1isRebooting = false;
unsigned long relay1rebootStarted;

void loop() {
  packetSize = Udp.parsePacket();
  if (packetSize > 0) { //we have received a packet
    // ...
    if (datReq == "relay1reboot") {
      digitalWrite(relay_1, HIGH); //relay off
      relay1isRebooting = true;
      relay1rebootStarted = millis();
    }
    // ...
  }

  // Switch back the relay 1 on if needed.
  if (relay1isRebooting && millis() - relay1rebootStarted >= 4000) {
      digitalWrite(relay_1, LOW); //relay on
      relay1isRebooting = false;
      Udp.beginPacket(Udp.remoteIP(), Udp.remotePort());
      Udp.print("relay 1 reboot");
      Udp.endPacket();
  }
}

Please note that the test for whether the relay 1 should be turned back
on is performed outside the if (packetSize > 0) block. Also note that
relay1rebootStarted has a valid value only when relay1isRebooting is
true.

for advanced coders: I usually use only the variable for millis. if it is 0 the timer is not running. if (relay1rebootStarted && millis() - relay1rebootStarted >= RELAY_DELAY)

@Juraj: I dislike this approach. Zero is a legitimate return value for millis(), returned every 49.7 days.


text:
Is it possible to remove the bootloader while flashing using the bootloader?
The question is meant as in, can I lock myself out of the Arduino using the bootloader, if I flash a hex file that doesn't contain the bootloader?
Or does the bootloader automatically add the flashed file after itself, so that it's never overwritten?
The device in question is an Arduino Pro Micro (ATMega32u4). Asking, because I don't have an ISP available right now, and I have to flash pre-compiled hex files.

If you don't play around ISP programming and have not already been playing around with ISP programming, your bootloader is fine and will remain fine no matter what you try to upload. The bootloader has its own protected section, so it's not necessary to tack it onto your sketch code on every upload. The Pro Micro bootloader can't be updated via itself anyway.
Worst case what you try to upload your precompiled binaries and they simply don't work.
You can upload code that fails to respond to the 1200 baud touch request that is used to reset the board into the bootloader, which may make you think you've screwed up the board, but you haven't. The Pro Micro version of Caterina bootloader supports a double-tap reset for an 8-second upload window no matter what you've put (or tried putting) on the chip.
Practically speaking, the existing bootloader is immutable and will always work for you until ISP becomes involved at some point.

Nice, that was the answer I was looking for, thanks!

as the question title doesn't mention the MCU, I just want to add a note that this answer doesn't apply to all MCU. even on the new AVR MCUs the bootloader is not protected by default

@Juraj: I had the ATMega32u4 both in the question and in the tag. Which new AVR MCUs do you refer to? I guess, you mean anything beyond the ATMega line? Your input is definitely valid.

@Dakkaron for example ATmega4809 used on Nano Every and Uno WiFi

The ATmega4809 doesn't support the protocol that Atmel/Microchip refer to as "ISP".

@Dakkaron I guess the idea is that you're asking about a specific board and anyone reading the answer will need to have read the question to understand the the answer only was intended to answer for the board in the question. I'm not sure what the likelihood is of anyone in that situation being inclined to read comments on the answer, but sure, I guess. If you want though you can just put "Pro Micro" in your question title: "Is it possible to remove the Pro Micro bootloader while flashing using the bootloader?"

@timemage From my understanding, that's what tags are there for. At least on Stackoverflow they tend to edit info like that away from the title. The device is prominently featured in the question, so no need for digging into the comments. Interesting fact about the ATMega4809. Haven't used that chip at all so far.

@Dakkaron I figured if their concern was going to be addressed it made sense to do it in the question title. I also think it's probably fine the way it is.


text:
List of supported boards in Arduino IDE 2.0
Where can I find the list of supported boards in Arduino IDE 2.0 without installing the IDE? Googling it was not fruitful. Specifically, I'm looking for ESP32-S3 support.

The 2.X IDE makes use of arduino-cli:

The backend operations such as compilation and uploading are offloaded
to an arduino-cli instance running in daemon mode.

which has roughly the same internals as arduino-builder

The arduino-builder is now just a wrapper of arduino-cli

which is what the 1.X IDE uses to launch the build process. Roughly speaking, they support the same boards.
About the only difference I've noticed is that the 2.X IDE does not yet support disableRTS and disableRTS board properties, so some ESP32 board that require these settings will not (yet) work in with the 2.X IDE's serial monitor. The ESP32-CAM-MB together with ESP32CAM is one combination where the Serial Monitor won't work. You can still upload with it though.
So, the IDE should compile and upload for your ESP32-S3 just fine. If you want to know whether or not the Serial Monitor will work, it's down to looking at the specific board schematic to see whether or not the EN/RESET and GPIO0 signals are connected to the serial transceiver using only diodes. The official boards don't do this. So if you have one of the Expressif devkits (or a clone) the 2.0 IDE Serial Monitor will work fine with it.

Where can I find the list of supported boards in Arduino IDE 2.0
Specifically, I'm looking for ESP32-S3 support.

Without knowing what you want to do, the short answer is: check this JSON's "boards" properties: https://raw.githubusercontent.com/espressif/arduino-esp32/gh-pages/package_esp32_index.json.
The Arduino IDE is just a user interface on top of the arduino-cli. It provides a way to change the board_manager#additional_urls property of the CLI configuration. Once a new 3rd party platform URL is specified in the IDE, the CLI will see the available boards of the platform. You'll need to install the platform to verify and upload your sketches. After installing the platform, the "boards.txt" will be available on your filesystem for the CLI. For this example, this is https://github.com/espressif/arduino-esp32/blob/master/boards.txt.


text:
Looking for a very simple board
I’ve worked with esp8266/esp32 boards in the past and they were great. But now I have a very simple project where both of these are way too powerful.
I want to read one analog input over USB per COM. That’s it. No wifi, no Bluetooth, no 32 bit or any of these fancy things.
It should be programmable without any hardware other than a computer though. It doesn’t need to be Arduino. All it has to do is to read the input and respond to serial communication.
But I’m absolutely overwhelmed by all these microcontrollers. Most of them are feature packed.
So I’m asking for a way to find a proper controller/board on my own. Feel free to recommend one though.

How about the Arduino Nano?

There is a non-exhaustive list of Arduino and similar boards on Wikipedia which may be of use in the comparison. https://en.wikipedia.org/wiki/List_of_Arduino_boards_and_compatible_systems?wprov=sfti1

Also there is a great article “When Less Is More - The Smallest Arduino Boards for Your Needs in 2022” by Matteo Parenti on all3dp.com with a well written comparison of small form factor arduinos and clones. https://all3dp.com/2/smallest-arduino-board/

Since you require USB, nano/micro are your way forward.
being mass produced anything smaller would actually turnout to be more expensive.
If you for those reading this message latter: If you do not need USB then you have a pro-miny (needs USB->ttl for programing)
If you are going really minimalist you can go with MSP430 chips (arduino programming available via PlatformIO).
Atmega32u4 can although run on its own without crystal, but I find Crystal free (using builtin crystal) run of MSP430 much better with timing.
Problem with MSP430 is that TI software development dedepartment is stuck in middle ages. (I am not sure if they even employ a full-time programmer) and if you are programming on arm, you might Have a problem compiling it from arm platform.

Since you seem to have some experience, seemingly these are valid options:

Obtain the smallest Arduino you can get. For example, a DigiSpark  original or clone, or a DFRobot Beetle. Use the Arduino IDE to program it.

Obtain the smallest AVR board you can get. For example, with an ATmega32u4. Download ASF, the Atmel Software Framework, learn how to use it. It provides a lot of sources for ADC and USB.

Keep in mind that sometimes "less is less".  The entire Arduino ecology is pretty cheap, so  maybe concentrate on ease-of-use instead of hardware features.  After all, if you value your time at some non-zero dollar amount, it may be that using a more 'feature-rich' (but still cheap) Arduino-ish board will be cheaper (and less frustrating) in the end.


text:
avr_boot change LED pin
I would like to know how can I change LED pin for avr_boot bootloader.
I can see there is option in variants folder but in the manual it mention "if using USE_LED adapt LED-pins in asmfunc.S" which is not clear. I am using pin PC3 how do I write it.

Near the top of asmfunc.S, you have these lines:
; LED Pins
#define DDR_SS  _SFR_IO_ADDR(DDRD), 5   // SS pin (PIN, PORT)
#define PORT_SS _SFR_IO_ADDR(PORTD), 5

#define DDR_PW  _SFR_IO_ADDR(DDRD), 6   // Power pin (PIN, PORT)
#define PORT_PW _SFR_IO_ADDR(PORTD), 6

These define the “write” or “slave select” LED pin as PD5 (registers
DDRD and PORTD, bit 5), and the “power” LED as PD6 (registers DDRD
and PORTD, bit  6).
These are the lines you have to change if using different pins. For
example, pin PC3 is: registers DDRC and PORTC, bit 3.

Got it. I am using port PC3 so how do I write it. Also do I have to do anything else.

I do not know what each of these LEDs mean. Regarding PC3, see amended answer.


text:
Wire.requestFrom() not a blocking function, even though it should be(?)
I'm working on creating a simple ACK/NACK handshake between 2 Arduino's that will essentially go like this:

Arduino 1 signals Arduino 0 it is available
Arduino 0 sends a connect byte to Arduino 1 (say, 'c')
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?

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.

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.


text:
ESP32 Rebooting while converting String to Hex Array
I wrote this 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(i%64)
                printf("\n");
            printf("%d, ",number[i]);
        }
}

void loop(){
}

But it is causing ESP32 to reboot.

Could anyone help me with the reason why?

I don't quite understand, what you are trying to do with your code. It doesn't make much sense to me. First: Why are you providing &temp to strtoul()? temp is an uninitialized pointer

Why do you write to number[0] two times instead of using number[i]? Why is that for loop only 5 iterations long, while the other, which does not write to number is 8199 iterations long? All in all I'm not sure how to help here other than pointing these things out. Maybe describe, what you are trying to do

@chrisl I corrected it, it was supposed to be number[i], after searching a bit I found a way to convert a string of hex values into array of hex values. So I have tried it in C online compiler it works fine.
Eg const char* hexstring = "0x21 0x49... becomes unsigned int number[8199]=[33, 73...

My bad, I edited the code to try a shorter string, and mistakenly copied that one. I corrected it now. Iteration is 8199

Still, why do you use temp uninitialized? At that position the parameter is the end pointer (pointer to where the conversion should stop). Null pointer here means conversion until end of string. So this comes down to if temp gets implicitly initialized to the null pointer. Might be the case for your online compiler. Please try using NULL instead of temp gor strtoul()

@chrisl, "where the conversion should stop"  It's actually used as at output not input. It doesn't tell strtoul where to stop lexing, it gives strtoul a means to tell the caller where it did stop. So you can use it to figure out where to resume your next operation, which is what they're doing. If you give it NULL you're just saying "I don't care where" you stopped. If you give it a pointer to a character pointer, you're saying "I do care where you stopped, tell me with this pointer that I'm pointing you at."

@timemage Ah, ok, then I guess I understood that wrong

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 ints) 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 that ultimately runs setup() for you. You can see that it calls getArduinoLoopTaskStackSize() returning ARDUINO_LOOP_STACK_SIZE which by default is 8192. 8192 bytes, not unsigned ints. With sizeof(unsigned int) being 4, this is very roughly in the vicinity of the 1800 unsigned ints 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 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:
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.


text:
Arduino outputting 4.7V instead of 3.3V when using I2C communication/sensor?
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

2) The working sensor shows 3.4V and outputs distance to serial

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

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

**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?

it is near impossible to guess correctly ... please provide a circuit diagram of the connections ... also provide a description of how you connected the voltmeter

@jsotola My project is a mess of wires and was hoping there are only so many reasons for such voltage incompatibility, but you're right, yall ain't clairvoyant. So I tried to isolate and detail the issue in the edit.

The Arduino Wire enables the internal pullup resistor 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.

Can't say I 100% understand the explanation, but tested it out with both a 560 and 18k resistor, and it really does go back to 3.3V, thanks! So the dead sensor pulls the 5V from I2C's pull-up resistor, because there's no load on the sensor...but then adding a load to 3.3V, it somehow ignores the 5V coming from I2C?
In the end, everything is fine and the board just isn't the highest "quality", with the mentioned worst case scenario of ~20K pull-up? Nothing to worry about and I can continue working with the board?

Also, since it's not exactly a specific sensor issue, is there a better title I could use? Like "Arduino outputting 4.7V instead of 3.3V when using I2C communication/sensor?". Can't find any posts about such an issue, so if someone's looking, they would realize that whatever is connected to 3.3V is just dead.

Interesting. Well, maybe I'll scrap that part of the answer. The principle part of it is that there is a path to 5V. It's not being spontaneously generated.  Internal to the ATMega2560 there is effectively a pair of resistors between 20K and 50K in value that can be enabled that connect SCL and SDA to VCC (5V).  They normally are enabled when you use the Wire library.  The load is relevant here because it is through a resistance. You could also get 5V actively driving them HIGH but I haven't seen your code. I'll watch the question for details.

Oh, was there something unexpected about my answer? Here's how the resistor testing looked, if you're curious - breadboard powered by 3.3V pin, with resistor and sensor in parallel. The code is just the basic example from "Adafruit_VL6180X" library, and there is nothing driving pins HIGH in the example, but maybe deeper in the library.
And since you're not mentioning anything about the Arduino board acting weirdly, I'll take it as a green light that it's working within acceptable parameters.

I'm not going to explain the entire thinking process in the comments. But, in short my experience with using and helping with this kind of board and attaching this kind of thing has lead me to tentative assumption a board usually fine unless user reported using voltages above 5V, smoke, heat, smell, or light or unless it has been rather definitely proved not-fine. If I get bored may play around with the same sort of experiment with resisters and a comparable Arduino or otherwise remove the part of the answer that you have more or less shown to be unhelpful.


text:
VP230 CAN Bus Transceiver
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.

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.

So may I ask, when I connect my VP230 to my arduino, and read serial from it, what data am I reading

I am assuming it is connected to the MCP2515 and that is converting the CAN data. However I do not know. It depends on what you have it hooked up to.
Connecting the VP230 to serial will probably just give you garbage, the format it will receive is not compatible with async serial.  You need the  MCP2515 or similar part to convert the data. CAN has a lot of control bits in its transmission that will not make sense unless you use a CAN controller chip.  You can have the Arduino convert that to serial if you want. Look at the send.ino and receive.ino in the Cory Fowler library.


text:
Code uploads to Due and fails to execute but runs on Redboard
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.

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;
};

What happens on the Due instead?

SPI on the Due is.... strange. There are multiple "channels" each using the same data / clock pins, but tied to specific chip select pins. Trying to use pins that aren't those specific chip select pins could have unwanted results. I don't know what those results will be, but I personally avoid the Due for anything, and especially anything where SPI is concerned.

@pmf Nothing happens on the due. There is no serial communication, even if I put the serial communication initialization and first serial print in the first two lines of the setup function. When I try to get the onboard LED to blink like in the "blink" sketch, nothing happens.

@Majenko So I have learned. I wish I knew that the Due was so difficult to deal with before I purchased it. Also the whole premise of having an "unrequired" pre-designated chip select (CS) pin is weird. Any other pin that can be switched be high and low can function as a CS pin.

Try putting a delay (of half a second or so) between Serial.begin() and the first print. Sometimes, the first characters are lost otherwise. I was able to get SPI to run on the Due, but that was some time ago.

When debugging with serial you should follow each print with a Serial.flush(); so that your program pauses until the message has actually been displayed, otherwise a crash later in the program will stop earlier messages from being displayed. Then put debugging between every non trivial line to see where it actually hangs.

@Majenko So I had tracked down the "bug" if that's what we want to call it. I don't know why it's a bug on the Due but not the Redboard though.  The things killing my program were the declarations of the global Thermocouple objects. I'm guessing it has something to do with the SPI.begin() inside the constructor of the class definition. I instead made a function that returns a new object which is set to a static variable in loop(). Why the Redboard doesn't have this issue is beyond me. Do either of you have any idea why the Redboard doesn't have this issue? I will try serial.flush() as well.

It is probably, yes, because the begin is in a constructor. One basic rule of Arduino coding is never put code that interacts with hardware in a constructor because that will run before the Arduino init routines which may break (entirely depending on the board) the hardware config that was done in the constructor.


text:
Conversion from `const char* datac="0x21,0x10,0xfa,0x7a,0xff";` to `uint8_t datat[]={0x21, 0x10, 0xfa, 0x7a, 0xff}`
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}?

almost the same question on SO with answer using standard library https://stackoverflow.com/questions/73969744/how-to-convert-const-char-root-0-title-0x21-0x32-i-0x0f-0x00-to-uint8-t-d

@Juraj I have tried it but I thought it was for probably C not Arduino C that's why its not compiling for ESP32. Also, it's a bit higher level for me to make changes. I wanted to know the for ESP32 perspective. But if you saying it should work with ESP32 too? I'll delete this question

you can use strtok (string tokenizer) and strtol (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, ",");
  }

const char* root_0_Title causing error as char * strtok ( char * str, const char * delimiters );

remove const from const char* root_0_Title ;


text:
Function call only works if called once
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);
  }
}

what happens if you run the first for loop twice?

@jsotola no LEDs light up

Your for loops are missing an initialization. You should write
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:
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:
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);.

Let this be a lesson for people who flit between Python & C++ too often. Also why did the question get a downvote?


text:
Shiftout only handles one shift register at a time
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?

For example:
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:

But with numbers of 8 bits or less the output is displayed correctly.
shiftOut(11, 13, LSBFIRST, 0b10001111);

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:
  shiftOut(11, 13, LSBFIRST, 0b1000111101);

should be:
  shiftOut(11, 13, MSBFIRST, 0b10);
  shiftOut(11, 13, MSBFIRST, 0b00111101);

The same thing still happens, in this case only the sixth led of the first row lights up.

What could it be? :(

I think it's the bit ordering that is wrong. Use MSBFIRST and not LSBFIRST?

It still does not work correctly, in this case the output on the LEDs is 1011110000. Could it be the simulator?

I just finished making my board, I loaded a programming with two shiftout and the output was displayed correctly, it is a problem of the simulator. Thanks for the help.

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.

I tried sending two shiftout but still the same thing happens :/

Could it be the simulator?

Yes, it might be, that the simulator doesn't handle the output of additional shift data to the next shift register. Though that is something, that only the creator of the simulator software can answer you.

I just finished making my board, I loaded a programming with two shiftout and the output was displayed correctly, it is a problem of the simulator. Thanks for the help.


text:
How do I control the speed of a 2-wire fan with an Arduino and only a potentiometer?
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:
int reading;
int value;

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

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

Assuming, that it is generally possible to control your fan via PWM (which is absolutely not guaranteed), you absolutely need a MOSFET to control it. A digital output pin cannot provide enough current for a fan (max 20mA)

would I require a mosfet or transistor despite using a potentiometer? ... what do you think that a potentiometer does?

@chrisl I see, thank you

@jsotola it varies the voltage output.

I guess jsotolas point is, that the potentiometer doesn't habe anything to do with the motor and the need for a MOSFET. The poti provides the input for the Arduino. The MOSFET/motor is the output. Input and output are only connected logically by the code

@chrisl If I am understanding this correctly, if I adjusted the pot the results produced by the code would change the output i.e. the fan speed varying?

@AI09 yes, you are understanding it correctly ... the pot only generates a numeric value ... the program uses that value ... the numeric value could just as easily come from a temperature sensor, or a light sensor, or from a mathematical calculation

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 and should be sufficient to control the speed of the motor.
// 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.

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.


text:
"Cast" BluetoothSerial to HardwareSerial
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?

Stream is the common base class https://arduino.stackexchange.com/questions/78719/can-you-use-serial-port-as-a-variable/78725#78725

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.


text:
Why does Serial.print(1) cost 228 bytes more program memory compared to Serial.print((char)(48+1))?
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 %10) + 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 %10) + 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

short answer: it is not the same print function. you could try .print('1') and .print((char) 1) too

@Juraj You are right, I tested always printing an integer in combination with above examples. And the the memory usage evens out at some point. I guess the compiler optimises the int print function out if you only ever print chars/strings. And vice versa. Which it would when they invoke different functions.

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.

So why not cast it to a char in the background then. As that takes less work, lots of less work ;)

@Gaai, because that is not what the int overload of .print() does in the general case. You cannot print .print(123); correctly with a single cast and addition. You're invoking the machinery that allows for correct printing of 123 even if you only ask for 1, and so you pay for that. The answer is correct.

print is a convinience function for easily printing different types as ASCII text. If all you want is to print a single character, then you shouldn't use print, but write. You yourself have to chosse the correct tool for your work

@chrisl Ah yes. This makes sense. That should be added to the answer! Serial.write(1) costs the same as the single char print.

@Majenko perhaps you can include the Serial.write option for single characters/digits in your answers? No memory difference then.

@Gaai The first bullet point "print this character" is the single character that you are opn about.

@Gaai Regarding Serial.write(1) <- .write() will get you out of the "danger" of accidentally calling the overload of print() that prints multi-digit numbers and perhaps express intention better, but that's all it does. It does not send 1 as a digit. So the .write(1) in your above comment sends a control character, not a digit. In other words you still need your + 48, you just don't need the cast  (char) with .write() the way you did print().

Well, my question was regarding a single digit int. Which is a single character as well as an int. But still print treats it like any int. Using more memory then it could have, treating it like a char.

@timemage you are right of course!

I added Serial.print(123) vs Serial.print("123") memory usage for completeness sake, just now.

Writing my own conversion still saves 80 bytes. Probably there is even more to gain if you do it smarter. Weird if you ask me.


text:
ESP_ATMod and its many library dependencies
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.

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":

Ah my mistake was not to set the board to ESP8266, it was still set to Arduino. The dependency error has now gone.