text:
Pushbutton firing somewhat randomly
I have a circuit which consists of a pushbutton and 2 relays.
The power supply is driven either over USB, where the circuit seems to work fine, or powered by a linear regulator board I've knocked together consisting of an LM78XX (see the next paragraph for detail), where the circuit exhibits the behaviour.
Detail of power supply:
The LM7808 was used to drive the main voltage into the Nano, via the VIN pin. It is supported by a 330n and 100n capacitor, as per the standard circuit diagrams for LM78XX chips. The LM7805 was also used to drive the nano via the 5v pin, as well as the Pico via its 5v pin. Using LM7805, I drove the 5v relay boards directly from the power supply, not utilising the onboard 5v regulator. Using the LM7808, I used the onboard 5v regulator to power the relay boards since they required 5v, not 8v. I have tried each of these configurations with no success.
I have 2 relay boards, each has 5v, GND, and IN. These take their 5v and GND directly from the same power supply driving the Arduino where possible, or from the regulator on the board where necessary (when powered by 8v).
On power up, the relays go to opposing states (one switches on, the other stays off).
I also have essentially a pushbutton, which currently consists of a choc block that I short out with a piece of wire by hand. I have had it pulled up by the Arduino, and shorting it to ground with the pushbutton. I have also had it pulled up manually, with a 10k resistor as per the circuit diagram below. In all configurations, note that it was a choc block and a piece of wire.

Now, for the unexpected behaviour. When I power this circuit over USB, the pushbutton works almost entirely. I may have seen it fail once or twice, I can't be sure. It seems to behave as expected 99% of the time. When I power it from a 12v power supply (into the LM78XX regulator) however, I only need to wave my hand near the choc block of the "pushbutton" and it will fire. Sometimes it will fire for seemingly no reason at all, other times I will need to connect a small length of wire only to the GPIO side of the choc block and it will fire the switch.
My current code is as below:
const int signal_1 = 10;
const int relay_1 = 11;
const int relay_2 = 12;
bool state = false;

void setup() {
  // put your setup code here, to run once:
  pinMode(relay_1, OUTPUT);
  pinMode(relay_2, OUTPUT);
  pinMode(signal_1, INPUT_PULLUP);

  digitalWrite(relay_1, LOW);
  digitalWrite(relay_2, HIGH);
}

void toggleRelays() {
  digitalWrite(relay_1, !state);
  delay(5000);
  digitalWrite(relay_2, state);
  state = !state;
}

void loop() {
  // put your main code here, to run repeatedly:
  int sensor_1_val = digitalRead(signal_1);

  if (sensor_1_val == LOW) {
    toggleRelays();
  }
}

I have simplified this as much as possible, and tried it in as many variations as I can think of. I still suffer from this interference issue.
Can anyone explain what might be happening here? Is it possible that I'm suffering from a brownout, and need to add an additional capacitor on the power supply? Is there something I'm obviously missing about the switch circuit?

add debugging code ... then start troubleshooting by removing relay activation in setup()

Does the problem persist when you remove the relays and just use simple LEDs to indicate the state of the output pins?

@chrisl I only got my box of LEDs out late last night and haven't tried this yet, so far as I can expect though it will. I'll find out today & update the question as/when.

"other times I will need to connect a small length of wire only to the GPIO side of the choc block" -- this does sound like your "pushbutton wire" acts as an antenna picking up some EMF emitted by some oscillation in your power supply chain.

@orithena that's exactly my thought, for some reason the microcontroller is over-sensitive to EMF. Waving a hand nearby occasionally works, other times I have to make contact with the GPIO pin, but I virtually never get to actually close the "pushbutton" because before I do, it fires. I'm starting to wonder if maybe I should edit the code to take the average high/low value of 20 GPIO reads, or maybe look for a rising edge and if possible measure the duration of the rise... Ultimately my 12v is a switching supply but I believe it to be rather clean, and it's plentifully filtered on the LM78XX.

@XtrmJosh Sounds like you'd need an oscilloscope to make sure that e.g. your LM78XX does not throw the feedback loop of your switching power supply into some resonating oscillation. (I'm a bit clueless about whether that could happen, I'm just clutching at straws here.)


text:
Upload to ESP32-C3 fails
I have built a custom circuit board using the ESP32-C3-MINI-1-H4 module (datasheet).
Here is a schematic:

I have the GND, Tx, and Rx lines hooked up to an Arduino Uno without the ATmega. The 3.3 V comes from an external power supply.
I have successfully put the chip into download mode (as shown from the serial output below).

ESP-ROM:esp32c3-api1-20210207
Build:Feb  7 2021
rst:0x1 (POWERON),boot:0x5 (DOWNLOAD(USB/UART0/1))
waiting for download

I attempted to upload an example sketch using the following settings (Arduino IDE).

I held down the reset button (S4) until the Rx light on the Uno started flashing.
It works about 5% of the time, but 95% of the time it ends in this:

A fatal error occurred: Failed to connect to ESP32-C3: No serial data received.

I'm not sure how that is possible, as the serial data appears on the oscilloscope, and it is clearly in download mode as shown by the serial output.
I have tried removing the voltage divider from the RX line, but that didn't help. Is there any way to make uploading more consistent?

"I held down the reset button(S4) until the Rx light on the uno started flashing", the correct sequence for putting the device into flash mode is to press and hold the FLASH button (io9) and press RESET(EN) once, then release(or hold) the FLASH button. BTW, read the Figure 7 of the datasheet on the reference design and the note below the diagram, you need a 1uF in parallel to your RESET switch otherwise your switch will bouncing during the reset.

// ESP32C3 USE DIO flash mode or it will not work !!!

You must be in flash mode DIO and watch the "USB CDC on boot" which must be on if you use native C3 usb and off if you use an external usb-serial converter.
You can upload OK in QIO mode but program wont start, that is EXACTLY what OP is asking.

Welcome to Arduino:SE  Please take a moment to read the Stack Exchange Expected behavior

This sounds like anecdotal evidence. Do you have any sources to back this up?

source: Stack Exchange

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

sort: votes


text:
code not getting uploaded to Arduino
when I try to upload any code to Arduino it isn't getting uploaded the "RX LED" keeps blinking about 10 times but the "TX LED" doesn't light up. I have done a loopback test but it failed the cable is working there is no problem with my cable "Pin 13 LED" and "ON LED" are working, also my Arduino is not getting recognized in the device manager, my Arduino was working before. My Arduino model is: "UNO R3".
the error I get when I upload the code:
An error occurred while uploading the sketch
avrdude: stk500_recv(): programmer is not responding
avrdude: stk500_getsync() attempt 1 of 10: not in sync: resp=0x49
avrdude: stk500_recv(): programmer is not responding
avrdude: stk500_getsync() attempt 2 of 10: not in sync: resp=0x49
avrdude: stk500_recv(): programmer is not responding
avrdude: stk500_getsync() attempt 3 of 10: not in sync: resp=0x49
avrdude: stk500_recv(): programmer is not responding
avrdude: stk500_getsync() attempt 4 of 10: not in sync: resp=0x49
avrdude: stk500_recv(): programmer is not responding
avrdude: stk500_getsync() attempt 5 of 10: not in sync: resp=0x49
avrdude: stk500_recv(): programmer is not responding
avrdude: stk500_getsync() attempt 6 of 10: not in sync: resp=0x49
avrdude: stk500_recv(): programmer is not responding
avrdude: stk500_getsync() attempt 7 of 10: not in sync: resp=0x49
avrdude: stk500_recv(): programmer is not responding
avrdude: stk500_getsync() attempt 8 of 10: not in sync: resp=0x49
avrdude: stk500_recv(): programmer is not responding
avrdude: stk500_getsync() attempt 9 of 10: not in sync: resp=0x49
avrdude: stk500_recv(): programmer is not responding

i dont have another Arduino to burn bootloder

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


text:
nRF52832 BLE "conn_handle" to disconnect the current connected devices
I'm working on nRF52832 Bluefruit Adafruit Module. I want the BLE connection to disconnect using a function and can call whenever required. But the issue is the disconnect function needs "conn_handle" to disconnect from the current connected Client.
Can anyone help me find where I can get the "conn_handle" of the connected client?
/**
 * Callback invoked when a connection is dropped
 * @param conn_handle
 * @param reason is a BLE_HCI_STATUS_CODE which can be found in ble_hci.h
 */
void disconnect_callback(uint16_t conn_handle, uint8_t reason)
{
  (void) conn_handle;
  (void) reason;

  connection_num--;

  // Mark the ID as invalid
  int id  = findConnHandle(conn_handle);

  // Non-existant connection, something went wrong, DBG !!!
  if ( id < 0 ) return;

  // Mark conn handle as invalid
  prphs[id].conn_handle = BLE_CONN_HANDLE_INVALID;

  Serial.print(prphs[id].name);
  Serial.println(" disconnected!");
}

The below complete code is for "Central Bleuart Multi"-
/*********************************************************************

 This is an example for our nRF52 based Bluefruit LE modules

 Pick one up today in the adafruit shop!

 Adafruit invests time and resources providing this open source code,
 please support Adafruit and open-source hardware by purchasing
 products from Adafruit!

 MIT license, check LICENSE for more information
 All text above, and the splash screen below must be included in
 any redistribution
*********************************************************************/

/* This sketch demonstrates the central API() that allows you to connect
 * to multiple peripherals boards (Bluefruit nRF52 in peripheral mode, or
 * any Bluefruit nRF51 boards).
 *
 * One or more Bluefruit boards, configured as a peripheral with the
 * bleuart service running are required for this demo.
 *
 * This sketch will:
 *  - Read data from the HW serial port (normally USB serial, accessible
 *    via the Serial Monitor for example), and send any incoming data to
 *    all other peripherals connected to the central device.
 *  - Forward any incoming bleuart messages from a peripheral to all of
 *    the other connected devices.
 *
 * It is recommended to give each peripheral board a distinct name in order
 * to more easily distinguish the individual devices.
 *
 * Connection Handle Explanation
 * -----------------------------
 * The total number of connections is BLE_MAX_CONNECTION (20)
 *
 * The 'connection handle' is an integer number assigned by the SoftDevice
 * (Nordic's proprietary BLE stack). Each connection will receive it's own
 * numeric 'handle' starting from 0 to BLE_MAX_CONNECTION-1, depending on the order
 * of connection(s).
 *
 * - E.g If our Central board connects to a mobile phone first (running as a peripheral),
 * then afterwards connects to another Bluefruit board running in peripheral mode, then
 * the connection handle of mobile phone is 0, and the handle for the Bluefruit
 * board is 1, and so on.
 */

/* LED PATTERNS
 * ------------
 * LED_RED   - Blinks pattern changes based on the number of connections.
 * LED_BLUE  - Blinks constantly when scanning
 */

#include <bluefruit.h>

// Struct containing peripheral info
typedef struct
{
  char name[16+1];

  uint16_t conn_handle;

  // Each prph need its own bleuart client service
  BLEClientUart bleuart;
} prph_info_t;

/* Peripheral info array (one per peripheral device)
 *
 * There are 'BLE_MAX_CONNECTION' central connections, but the
 * the connection handle can be numerically larger (for example if
 * the peripheral role is also used, such as connecting to a mobile
 * device). As such, we need to convert connection handles <-> the array
 * index where appropriate to prevent out of array accesses.
 *
 * Note: One can simply declares the array with BLE_MAX_CONNECTION and use connection
 * handle as index directly with the expense of SRAM.
 */
prph_info_t prphs[BLE_MAX_CONNECTION];

// Software Timer for blinking the RED LED
SoftwareTimer blinkTimer;
uint8_t connection_num = 0; // for blink pattern

void setup()
{
  Serial.begin(115200);
  while ( !Serial ) delay(10);   // for nrf52840 with native usb

  // Initialize blinkTimer for 100 ms and start it
  blinkTimer.begin(100, blink_timer_callback);
  blinkTimer.start();

  Serial.println("Bluefruit52 Central Multi BLEUART Example");
  Serial.println("-----------------------------------------\n");

  // Initialize Bluefruit with max concurrent connections as Peripheral = 0, Central = 4
  // SRAM usage required by SoftDevice will increase with number of connections
  Bluefruit.begin(0, 4);

  // Set Name
  Bluefruit.setName("Bluefruit52 Central");

  // Init peripheral pool
  for (uint8_t idx=0; idx<BLE_MAX_CONNECTION; idx++)
  {
    // Invalid all connection handle
    prphs[idx].conn_handle = BLE_CONN_HANDLE_INVALID;

    // All of BLE Central Uart Serivce
    prphs[idx].bleuart.begin();
    prphs[idx].bleuart.setRxCallback(bleuart_rx_callback);
  }

  // Callbacks for Central
  Bluefruit.Central.setConnectCallback(connect_callback);
  Bluefruit.Central.setDisconnectCallback(disconnect_callback);

  /* Start Central Scanning
   * - Enable auto scan if disconnected
   * - Interval = 100 ms, window = 80 ms
   * - Filter only accept bleuart service in advertising
   * - Don't use active scan (used to retrieve the optional scan response adv packet)
   * - Start(0) = will scan forever since no timeout is given
   */
  Bluefruit.Scanner.setRxCallback(scan_callback);
  Bluefruit.Scanner.restartOnDisconnect(true);
  Bluefruit.Scanner.setInterval(160, 80);       // in units of 0.625 ms
  Bluefruit.Scanner.filterUuid(BLEUART_UUID_SERVICE);
  Bluefruit.Scanner.useActiveScan(false);       // Don't request scan response data
  Bluefruit.Scanner.start(0);                   // 0 = Don't stop scanning after n seconds
}

/**
 * Callback invoked when scanner picks up an advertising packet
 * @param report Structural advertising data
 */
void scan_callback(ble_gap_evt_adv_report_t* report)
{
  // Since we configure the scanner with filterUuid()
  // Scan callback only invoked for device with bleuart service advertised
  // Connect to the device with bleuart service in advertising packet
  Bluefruit.Central.connect(report);
}

/**
 * Callback invoked when an connection is established
 * @param conn_handle
 */
void connect_callback(uint16_t conn_handle)
{
  // Find an available ID to use
  int id  = findConnHandle(BLE_CONN_HANDLE_INVALID);

  // Eeek: Exceeded the number of connections !!!
  if ( id < 0 ) return;

  prph_info_t* peer = &prphs[id];
  peer->conn_handle = conn_handle;

  Bluefruit.Connection(conn_handle)->getPeerName(peer->name, sizeof(peer->name)-1);

  Serial.print("Connected to ");
  Serial.println(peer->name);

  Serial.print("Discovering BLE UART service ... ");

  if ( peer->bleuart.discover(conn_handle) )
  {
    Serial.println("Found it");
    Serial.println("Enabling TXD characteristic's CCCD notify bit");
    peer->bleuart.enableTXD();

    Serial.println("Continue scanning for more peripherals");
    Bluefruit.Scanner.start(0);

    Serial.println("Enter some text in the Serial Monitor to send it to all connected peripherals:");
  } else
  {
    Serial.println("Found ... NOTHING!");

    // disconnect since we couldn't find bleuart service
    Bluefruit.disconnect(conn_handle);
  }

  connection_num++;
}

/**
 * Callback invoked when a connection is dropped
 * @param conn_handle
 * @param reason is a BLE_HCI_STATUS_CODE which can be found in ble_hci.h
 */
void disconnect_callback(uint16_t conn_handle, uint8_t reason)
{
  (void) conn_handle;
  (void) reason;

  connection_num--;

  // Mark the ID as invalid
  int id  = findConnHandle(conn_handle);

  // Non-existant connection, something went wrong, DBG !!!
  if ( id < 0 ) return;

  // Mark conn handle as invalid
  prphs[id].conn_handle = BLE_CONN_HANDLE_INVALID;

  Serial.print(prphs[id].name);
  Serial.println(" disconnected!");
}

/**
 * Callback invoked when BLE UART data is received
 * @param uart_svc Reference object to the service where the data
 * arrived.
 */
void bleuart_rx_callback(BLEClientUart& uart_svc)
{
  // uart_svc is prphs[conn_handle].bleuart
  uint16_t conn_handle = uart_svc.connHandle();

  int id = findConnHandle(conn_handle);
  prph_info_t* peer = &prphs[id];

  // Print sender's name
  Serial.printf("[From %s]: ", peer->name);

  // Read then forward to all peripherals
  while ( uart_svc.available() )
  {
    // default MTU with an extra byte for string terminator
    char buf[20+1] = { 0 };

    if ( uart_svc.read(buf,sizeof(buf)-1) )
    {
      Serial.println(buf);
      sendAll(buf);
    }
  }
}

/**
 * Helper function to send a string to all connected peripherals
 */
void sendAll(const char* str)
{
  Serial.print("[Send to All]: ");
  Serial.println(str);

  for(uint8_t id=0; id < BLE_MAX_CONNECTION; id++)
  {
    prph_info_t* peer = &prphs[id];

    if ( peer->bleuart.discovered() )
    {
      peer->bleuart.print(str);
    }
  }
}

void loop()
{
  // First check if we are connected to any peripherals
  if ( Bluefruit.Central.connected() )
  {
    // default MTU with an extra byte for string terminator
    char buf[20+1] = { 0 };

    // Read from HW Serial (normally USB Serial) and send to all peripherals
    if ( Serial.readBytes(buf, sizeof(buf)-1) )
    {
      sendAll(buf);
    }
  }
}

/**
 * Find the connection handle in the peripheral array
 * @param conn_handle Connection handle
 * @return array index if found, otherwise -1
 */
int findConnHandle(uint16_t conn_handle)
{
  for(int id=0; id<BLE_MAX_CONNECTION; id++)
  {
    if (conn_handle == prphs[id].conn_handle)
    {
      return id;
    }
  }

  return -1;
}

/**
 * Software Timer callback is invoked via a built-in FreeRTOS thread with
 * minimal stack size. Therefore it should be as simple as possible. If
 * a periodically heavy task is needed, please use Scheduler.startLoop() to
 * create a dedicated task for it.
 *
 * More information http://www.freertos.org/RTOS-software-timer.html
 */
void blink_timer_callback(TimerHandle_t xTimerID)
{
  (void) xTimerID;

  // Period of sequence is 10 times (1 second).
  // RED LED will toggle first 2*n times (on/off) and remain off for the rest of period
  // Where n = number of connection
  static uint8_t count = 0;

  if ( count < 2*connection_num ) digitalToggle(LED_RED);
  if ( count % 2 && digitalRead(LED_RED)) digitalWrite(LED_RED, LOW); // issue #98

  count++;
  if (count >= 10) count = 0;
}

GitHub Source code
I want to invoke this disconnect function, but I don't know where to get conn_handle. If anyone has any idea please help me.
I have already tried going into libraries; the best it shows is just the definition of the callback function:
1: Bluefruit.Central.setDisconnectCallback(disconnect_callback);

2: void BLECentral::setDisconnectCallback( ble_disconnect_callback_t fp )
   {
     _disconnect_cb = fp;
   }

3: class BLECentral
   {
     ...
     private:
       ble_disconnect_callback_t _disconnect_cb;
   }

4: typedef void (*ble_disconnect_callback_t ) (uint16_t conn_hdl, uint8_t reason);

This is all I got regarding this disconnect function in different libraries following the definition but nothing related to conn_handle.

Idk if its a right or not but it works.
When there's is a new connection established, "connect" gets revoked, with "conn_handle" as its argument. If someone knows please tell how is this function revoke itself.
But what I did is make a global variable uint16_t conn_handle
uint16_t g_conn_handle;
void connect_callback(uint16_t conn_handle)
    {
      g_conn_handle=conn_handle;
      // Find an available ID to use
      int id  = findConnHandle(BLE_CONN_HANDLE_INVALID);

      // Eeek: Exc
      ...

Now I can call the Disconnect function with this g_conn_handle global variable.


text:
Tasks in ESP32: guidelines rather than blink example
I'm using an ESP8266 for IOT devices.
I wish to work with an ESP32 and harvest its benefits - for my uses managing WiFi and MQTT connectivity.
Most tasks examples are very basic and quite the same (blinking LEDs). But for a real time application, more data is needed for which I can't find a guide.
For example:

when to use core0 or core1?
How to evaluate stack size needed for a task?
Are there any limitation for a task? Is a mqtt.loop()  for example, ligit, memory wise?

I'd be happy to read about real life-implementations for tasks (especially "dos" and "don'ts")
Example usage from ESP32 DOCS
 // Dimensions the buffer that the task being created will use as its stack.
 // NOTE:  This is the number of bytes the stack will hold, not the number of
 // words as found in vanilla FreeRTOS.
#define STACK_SIZE 200

 // Structure that will hold the TCB of the task being created.
 StaticTask_t xTaskBuffer;

 // Buffer that the task being created will use as its stack.  Note this is
 // an array of StackType_t variables.  The size of StackType_t is dependent on
 // the RTOS port.
 StackType_t xStack[ STACK_SIZE ];

 // Function that implements the task being created.
 void vTaskCode( void * pvParameters )
 {
     // The parameter value is expected to be 1 as 1 is passed in the
     // pvParameters value in the call to xTaskCreateStatic().
     configASSERT( ( uint32_t ) pvParameters == 1UL );

     for( ;; )
     {
         // Task code goes here.
     }
 }

 // Function that creates a task.
 void vOtherFunction( void )
 {
     TaskHandle_t xHandle = NULL;

     // Create the task without using any dynamic memory allocation.
     xHandle = xTaskCreateStatic(
                   vTaskCode,       // Function that implements the task.
                   "NAME",          // Text name for the task.
                   STACK_SIZE,      // Stack size in bytes, not words.
                   ( void * ) 1,    // Parameter passed into the task.
                   tskIDLE_PRIORITY,// Priority at which the task is created.
                   xStack,          // Array to use as the task's stack.
                   &xTaskBuffer );  // Variable to hold the task's data structure.

     // puxStackBuffer and pxTaskBuffer were not NULL, so the task will have
     // been created, and xHandle will be the task's handle.  Use the handle
     // to suspend the task.
     vTaskSuspend( xHandle );
 }

in a real time application, more data is needed which I can't find a guide for it

That is because there isn't one. The amount of memory needed is completely defined by the application and the task you want to run, so no "guide" can tell you what that will be.
You will have to analyze the actual software you want to run to see what it does and how it works to estimate the likely size of stack needed (note: stack is used for local (non-static) variables as well as storage for registers when calling functions). It's entirely up to you to work it out. The basic assumption (since the SDK is aimed at professional users not hobbyists like typical Arduino users) is that you know what your software is doing since it's you writing that software.

when to use core0 or core1?

When you need to balance your processing load. Again that's entirely down to your software and how you need it to work. Maybe you have one task that has to have almost exclusive use of a core - in which case you bind everything except that task to the same core, and place that task on its own core. Or maybe you just want to spread the tasks out evenly. It's your choice.

Are there any limitation for task?

Yes. The chip only has finite memory. You can't give a task more memory than there is. Also be aware that there may be a watchdog monitoring your tasks so you have to be sure to "kick" it regularly and not block too long.


text:
Is it possible to use Nano with mblock and oldbootler?
I've old Nanos that to program (upload) with Arduino IDE I have to select "ATMEGA328P Old Bootloader".   The programming is via the standard Nano USB cable, and I need the CH340 driver under Windows 7.
With mblock (ide) I've selected the nano device package, but when I go to program the nano with the scratch program, the COM port is available, but the device is never found.   I suspect this is due to the old bootloader.  Is there a way to make use of the old bootloader under mblock?
[At this time not looking to re-flash my Nanos with a separate programmer.]
TIA.

"TIA" <- I hated this before I bothered looking it up. Anyway, I've never heard of this thing before. The developers section of the website seems to take me to a login screen in Chinese which isn't helpful. My only suggestion is it that if it claims to support Diecimila with 328P maybe try that. So far as I can tell they're largely compatible board definitions. If it works for you can write your own answer or someone can turn it into a community answer or whatever.

Couldn't figure out how to send makeblock the question...  But maybe new Nano's are the price I need to pay...

I'm taking the above to mean that you did not find Diecimila as an option. Re: "separate programmer". You understand that a "programmer" can be one of your Nanos, some jumpers, a breadboard, and a capacitor with the ArduinoISP sketch? So, if you're about saving money, you don't necessarily need to buy anything. Anyway, that's all I have to offer.


text:
Does avr-libc have any reason to word-align C++ class member variables?
This sounds straightforward enough, but I'm struggling to find a good answer.
Suppose I declare a C++ class with private members that collectively occupy an odd number of bytes. Say...
class Foo {
private:
    uint8_t bitflags;
    uint32_t millis;
}

or
class Foo {
private:
    uint8_t rawData[3];
}

If I compile it using GCC or Clang (possibly, wrapped inside the Arduino IDE, or multiply-wrapped inside PlatformIO, CMake, and an IDE like CLion), is there any likely scenario where the compiler (when targeting 8-bit AVR... specifically, the ATmega2560 on an Arduino Mega2560) would be inclined to add padding bytes to the portion of the class stored in SRAM? Say... between bitflags and millis, or between an instance of Foo and a uint64_t right after it?
If yes, what do I need to use to tell the compiler, "absolutely, positively DO NOT pad variables in SRAM (and, if you find yourself in a situation where it's seemingly unavoidable, at least output a prominent compile-time warning, if not an outright compilation-stopping error)?
Then... if I do that... are there any negative consequences to doing that with code that's targeting (and ultimately running upon) an 8-bit AVR?
As far as I know, 8-bit AVR has never had specific opcodes for copying a pair of consecutive bytes between registers and SRAM (I think, because Atmel literally ran out of opcode mapping space, and had nowhere to put hypothetical new opcodes like, "ldw rz, $f00d"), and movw only applied to pairs of registers... so, in theory, there's no reason for the compiler to "optimize" SRAM access to be word-aligned.
That said... I suppose it's not inconceivable that a compiler might default to word-alignment (even on platforms where it doesn't matter), just for the sake of ABI consistency between different platforms.
Before someone suggests, "try it and see!"... I've gotten far enough into learning C++ to know that with C++, you can't trust "compiles without errors and passes unit tests on my computer, with {this} IDE" as a general-purpose proof-of-correctness for C++ involving "implementation-defined" or "undefined" behavior. AFAIK, padding behavior is "implementation-defined".

Re “padding behavior is ’implementation-defined’”: My understanding is that it is defined by the ABI: the padding rules used in a compiled library must match those of the calling code. So you can try and see.

It didn't seem completely nuts to me that they could have chosen to align words in structs because they are passed in registers (if small enough) in the calling convention and because the pairs used by MOVW are always aligned in the sense that they're even:odd pairs (which also become aligned in the memory mapped register file (when it is mapped). That said, it doesn't appear (from tests) that they did this, probably because it wasn't worth bloating structures that may not ever be optimized with MOVW usages. I have no idea what sort of answer would satisfy this question.

OK, how about if I simplify it a bit, and we're talking about a class whose only member is a uint8_t[3]. Basically, I want to make sure that if I bend over backwards & do my own complicated bit-packing to make everything fit into 3 bytes, the compiler isn't going to just laugh at me and make it take 4 bytes anyway.

It kind of sounds like you're heading in the direction of something like a GCC extension __attribute__ ((__packed__)) or the #pragma or C++ attribute way (way; it's still non-standard) of specifying it, but really I don't know. I expect this attribute does nothing in avr-gcc because it would seem to be the normal behaviour in that compiler under common options anyway. But again... I don't know.

GCC has an extension to add attributes to types, which you can use to tell it your alignment requirements.
Additionally it has a #pragma to define the alignment, which could be used alternatively.
But as you already suspect, for this 8-bit target there should be no reason to insert padding bytes.

So your question boils down to find a method to detect unwanted padding. You can do this in a standard compliant way, which I show below. Yes, it does introduce additional types, one per structure. But it does not generate any unnecessary objects that eat your precious resources.
The "trick" is to use the sizeof operator to calculate a valid array size only, if the size of the checked type meets the expectation. If not, a compiler error safely breaks the generation of code. Granted, the error message is misleading an unsuspecting user, so it is really necessary to name the macro and the type accordingly.
This example compiles successfully with a PC as target, but not with an AVR as target. This is intentionally to demonstrate the working, because with an AVR target the type UP should have no padding bytes.
#define ASSERT_TYPE_SIZE(Type, size) \
    typedef char Assert##Type##Size[2 * (sizeof(Type) == (size)) - 1]

typedef struct {
    char c;
    long l;
} UP;
ASSERT_TYPE_SIZE(UP, sizeof (long) + sizeof(long));

typedef struct __attribute__((packed)) {
    char c;
    long l;
} P1;
ASSERT_TYPE_SIZE(P1, sizeof (char) + sizeof(long));

#pragma pack(1)
typedef struct {
    char c;
    long l;
} P2;
ASSERT_TYPE_SIZE(P2, sizeof (char) + sizeof(long));
#pragma pack()


text:
Use same pin for two purposes
I have only one pin available and I'd need to use it both for a digitalRead and for sending serial messages (assigning it the Tx role within a SoftwareSerial). I can alternate these two operations, but I don't seem to succeed. I could be interested in other pairs as well (digitalRead+Rx, digitalWrite+Tx and digitalWrite+Rx) and I hope that understanding one will solve them all, but for now I'd be happy to get the first one working. My first naive attempt would be something like:
 #include <SoftwareSerial.h>

SoftwareSerial swSerial(7,6);
int val;

void setup() {

  pinMode(6, INPUT_PULLUP);

}

void loop() {

  val = digitalRead(6);

  delay(2000);

  swSerial.begin(19200);
  swSerial.print("myData");
  swSerial.end();

  delay(2000);

}

But I've made other experiments, for example with a digitalWrite, hoping that combining two forms of output would be feasible, but again no way. I know I can alternate a pin role between output and input as long as common digital read/write operations are involved, but SoftwareSerial appears to be less flexible. It seems to me it refuses to work as soon as the pin is declared/used for common digital purposes. Is there a way to accomplish my goal?
I guess that similar requirements and fixes (make a pin role more flexible) led to the Software Serial with Half Duplex library, but I'd refrain from adopting it because I feel it is overcomplicated and seems like overkill for my purpose, moreover it doesn't seem actively supported.
To avoid a XY problem, my very initial need (I may have further ones, requiring the different pairs mentioned at the beginning) would be to check whether this pin is floating or connected to something (I can chose between Vcc or Gnd, setting up the pull-up or an external pull-down accordingly) and to send back some information (obviously this is useful if the pin is actually connected, but I have no reason not to send data anyway) alternating the tasks a few times per second at least.

why do you have only one pin available?

Check out my answer to your previous post of this question.

@jsotola it's an hardware-driven requirement

Before trying to write the software, invent the method how the external hardware can differentiate between both purposes. For example, if you want to read a digital value, the external hardware drives the wire. How do you control it to release the wire so that the Arduino can drive the wire? And, how do you control the hardware driven by TX that only during sending it shall read the value on the wire, and not during the time the Arduino reads the other device? Please [edit] your question and add this important information.

@Gil What are you talking about? I'd guess there is a similar question I couldn't find when posting mine (it would be nice to have a link to it) and you assumed I asked twice hiding my identity, which is somewhat disrespectful (considering that I have a decent profile on other SE)

@thebusybee Suppose I have my pin with pull-up enabled. My idea is to have the external hardware to have a stronger pull-down, so that I can recognize it being attached finding my pin driven to LOW. Yet the external hardware stays ready to ready my data

OK. But this LOW would be interpreted as a start bit (and depending on the duration of the LOW and the used baud rate as additional data bits) on the TX line. How do you prevent this?

If I did the opposite? My pin waiting on LOW, the external one driving it to HIGH, then I swap my pin to serial and start transmission Or maybe I could set SoftwareSerial to work with inverse_logic (I'm not sure if this means a low idle too)

From your comments it seems to me, that you only have one external hardware connected to the pin, but you want to first check for its presence before sending data to it. Is that correct, or do you have multiple different hardware connected to that pin?

@chrisl Correct, only one external hardware! Arduino needs to know when this is connected, while it (when connected) needs to receive data from the Arduino. I have no problem sending data in any case (obviously it will be received only when there is connection) but Arduino needs to know when the external hardware is present. Checking if the information is correctly received wouldn't harm, but it's not necessary.

Is it hardware that you build/program yourself or hardware that will give an answer if you send it fitting data? Normally one would just use a simple handshaken meaning that your Arduino send a simple command and listens for the answer. If no answer is received there is nothing connected and you can try again later. Would that fit for you?

Yes, definitely! It's even more than needed! I will probably have a chance to drive the choice of the external hardware, it may be another Arduino. That was the idea behind the Serial with Half Duplex possible solution. I may need to be able to repeat the same principle more than once (n pins, brought in separate locations, each one having the need to sense if ITS hardware is connected). And I'd feel more comfortable with a robust solution, not an almost experimental library that hardly I'd be able to debug...

I still don't understand why the question is downvoted...

First of all, for using the Software Serial you need to set your tx and rx pins to OUTPUT, that what the library does under the hood.
What you may try to do is to set a millis timer (forget about delay(), never ever use it) and change pin mode to INPUT once every 200ms let's say. And after your measurements put it back to output as soon as you can.
200ms delay is normally ok for some readings like button click. If you can read the value more rare do it (for example you may read some sensor value only once per hour). Here is an example:
    #include <SoftwareSerial.h>

SoftwareSerial swSerial(7,6);
int val;

byte timer = 200; // Read value every 200ms
uint32_t prevTime = 0;

void setup() {

    // Don't change pin mode here
    swSerial.begin(19200);

}

void loop() {

    if (millis() - prevTime > timer) {
        // you could try swSerial.flush(); here...
        prevTime = millis(); // reset timer
        pinMode(6, INPUT_PULLUP); // changing pin mode and reading value
        val = digitalRead(6);
        pinMode(6, OUTPUT); // changing pin mode back
    }

    swSerial.print("myData");
    // swSerial.end(); // I don't think you need this line;

}

It may be a solution from a programming point of view. But another task is to organize an electric multiplexing for 2 different devices on the same pin as was mentioned by @the busybee

I'll try this straight away!

It works! Thank you! Let me ask you this: are you sure that tx AND rx need pins set to output? It seems to me that the setRX method (line 282 here: https://github.com/arduino/ArduinoCore-avr/blob/master/libraries/SoftwareSerial/src/SoftwareSerial.cpp) called by the constructor sets the rx pin as input, as one would guess. If I wanted to alternate digital read and swSerial read, cannot I leave the pin mode untouched? (apart from pull-ups). I didn't succeed at my first attempt, but I had only a few minutes left and I may have mistaken something else.

As I thought, I just had to debug the code, now it works also alternating digital and serial readings, no need to change the pin's destination: the rx pin has to be input. Thank you!

You're right, Rx (receiver) is INPUT, but Tx (tranceiver) is OUTPUT. You can leave th Rx pin untouched, and change only the mode of Tx pin. BUT!!! You need to be sure that the value you're reading is not from the Serial. You will need serial.flush, some timing or even maybe some physical solution on diods and transistors. It depends on your exact task and conditions.


text:
Uno: Infrared Transmitter Module Not Transmitting
I purchased https://www.jaycar.co.nz/medias/sys_master/images/images/9677365510174/XC4426-dataSheetMain.pdf, which seems identical to https://arduinomodules.info/ky-005-infrared-transmitter-sensor-module/.
I connected the module according to the diagram:

I then copied the following Sketch:
#include <IRremote.h>
IRsend irsend;
void setup()
{
    Serial.begin(9600); // Initialize serial interface
}
void loop()
{
    for (int i = 0; i < 10; i++) {
       irsend.sendSony(0xa90, 12); // code for Sony TV power command
       delay(5000); // wait 5 seconds
   }
}

When I compiled the above, I got the following warning:

warning: 'void IRsend::sendSony(long unsigned int, int)' is deprecated: This old function sends MSB first! Please use sendSony(aAddress, aCommand, aNumberOfRepeats).

So, I modified the code and added a 3 for the aNumberOfRepeats parameter. Thus, my final Sketch was this:
#include <IRremote.h>
IRsend irsend;
void setup()
{
    Serial.begin(9600); // Initialize serial interface
}
void loop()
{
    for (int i = 0; i < 10; i++) {
       irsend.sendSony(0xa90, 12, 3); // code for Sony TV power command
       delay(5000); // wait 5 seconds
   }
}

When I ran the Sketch on my Uno and viewed the module through my camera phone, I did not see the module blinking. My assumption is that this is not working for some reason. Any ideas why?
Also, I'm measuring about 4.5 volts between GND and the middle pin. That seems right. When I measure GND and the signal out pin, I get a steady 0.64 volts. Shouldn't that be toggling between 0 and some number?
UPDATE per @orithena's comment:
I've updated the code as per suggested, but the transmitter still doesn't blink when viewed through my camera phone:
#include <IRremote.h>

IRsend irsend;

#define IR_SEND_PIN 5

void setup()
{
    pinMode(IR_SEND_PIN , OUTPUT);
    Serial.begin(9600);
}

void loop()
{
    for (int i = 0; i < 10; i++) {
       irsend.sendSony(0xa90, 12, 255);
       delay(1000);
   }
}

Just a few notes about this new code:

I tested connecting S to pins 3 and 5; neither worked
255 is the highest number I could set for aNumberOfRepeats, otherwise I would get a compile warning: "warning: large integer implicitly truncated to unsigned type"

UPDATE per @jsotola's comment:

It may be that everything is blinking too fast for you to see or measure. Or, your pin 3 may be broken. Try explicitely initializing the pin: pinMode(3, OUTPUT); in setup. Try changing the signal pin: insert #define IR_SEND_PIN 5 at the very top of your sketch and connect S to pin 5. Try increasing the number of repeats to 1000, so that the LED blinks longer.

Please see my update.

Why are you using 0xa90 as Sony remote address, and 12 as command code? See the example code for Sony remote control. If you are not sure, run MinimalReceiver and point your remote to the arduino to decode the IR code, and then use it for your IR_send sketch.

On your updated code, if you explicitly #define IR_SEND_PIN 5;, then your pinMode() function should be pinMode(IR-SEND_PIN, OUTPUT). Don't just copy and paste the code, try to understand the code.

why did you connect the 5 V ? ... that module uses only two pins ... it needs only data and ground connections

@jsotola the diagram I followed connected all three pins.

@hcheung I don't care what signal I'm sending. I just want to see a signal to be sent. I'm not seeing anything through my camera phone. Also, I did use pinMode(IR_SEND_PIN, OUTPUT)  in one of my tests (when I connected to pin 5; it didn't work.

the crazy part is that you are wasting your time with arduino programming ... all you have to do, is to connect the module to a 5 V power supply and it should light up

please post clear, well lit pictures of the front and back of the IR emitter module ... I have a suspicion that a component is missing from it

@jsotola - I tried attaching the transmitter to GND and 5V only (no programming). I still don't see anything thought the camera phone. Would that suggest that the device is defective? Also - see photos in my post per your request.

the pictures are not very clear ... it looks like a resistor may be missing ... it is quite possible that the the board is incomplete

@jsotola - The operating voltage of the infrared transmitter module is 5VDC. No need for a resistor, right?

Hooking an IRED/LED directly to a voltage source is a time-honoured way of creating Dark Emitting Diode.

It really looks like R1 is missing. And yes, the operating voltage of the whole module is 5V -- the (typically) 1.5V forward voltage of the IR Diode is reached in a 5V circuit by using a 220Ohm resistor. Therefore, changing the resistor changes the operating voltage of the module. And: if it is missing, there is no electrical connection from the module's signal pads to the LED itself, so the LED cannot turn on.

I'll get another transmitter in case I now have a "Dark Emitting Diode", @timemage. Where would I connect R1, @orinthena?

Someone can tell you about IREDs/LEDs generally, but it's not really a good answer to the question. It would a better answer if someone could answer with some certainty about how your particular boards are made. The best resources I can find on the design of that board are very poor. If I had one, I would use a meter to determine the exact nature of the board before writing an answer. So far the only one here known to have this board is you. So the question seems mostly answerable (well) by you, so far anyway.

@ArduinoNewbie On the pads marked with R1... well, scratch that. I just devoted an hour finding more info on the KY-005 module. I found it to be one of the most underdocumented module I've ever seen. It seems to have a place for a resistor to solder in, but thats not documented anywhere except in some reverse engineering blog (also, if you solder one in, use the middle pin instead of S). Its sold everywhere listed with an operating voltage of 5V, but without R1, it'd be at most 1.5V. It's just an IR LED soldered to a PCB. Better unsolder the LED and use it directly (with 220Ohm resistor).

Although you might've run into the "Dark Emitting Diode" problem already, since I'm now pretty sure that you did put the full 5V onto the IR LED (that module is just bad: every shop tells you "it's for 5V! put it on your Arduino!" when the resistor is missing that should reduce the 5V to 1.5V). It may be that the LED is now shorting your Arduino pin to GND, so that pin may have taken some damage. Try another pin (don't forget to adapt the software to use another pin!) when you try a new IR LED.


text:
Methods of programming the Arduino
I took a look at a barebones Arduino schematic.
It had three different ways of programming the chip.

The first interface is for programming through SPI (For example with "Pocket AVR Programmer", or "USBTinyISP").
The second interface is for programming through an FTDI to USB module.
What is the third programming interface? It only has MOSI, MISO and SCK.
EDIT: This is a picture of the full schematic. Unfortunately, I could not find the link from which I downloaded it. I am sure it was from Github though.

Please include/link the full schematics. From what you posted, I can only say that the first two pin headers both connect to the same UART pins (RXD/TXD, making both the same UART programming interface, just with differently-shaped pin headers) and the third connects to the SPI pins of the chip -- but I would think that that pin header is there to connect SPI periphery/sensors, not for ICSP (in-circuit serial programming).

@orithena I updated the question with the full schematic.

Okay, that clears up the level of "barebone-ness" :)

JP2 and JP8 are both serial pin headers suitable for programming -- they connect to the same pins of the chip: RXD, TXD and RST. This is programming via UART: A bootloader software (which has to be "pre-burnt" in the chip's flash memory) is the first thing that is run after a reset (RST) signal. It waits a little moment for data to arrive on RXD. If data arrives, the bootloader goes into programming mode: the data is written to flash memory, making it the firmware to be executed after the next RST. (If no data arrives: well, then the firmware that already is there is executed.)
Programming the chip via JP4 would use "hardware-supported" programming interface via SPI, recognizeable by the pins MISO, MOSI and SCK. That is the only way to get the first bootloader into the flash memory. It also provides you with a way to flash and re-flash a firmware without a pre-burnt bootloader (making the bootloader space available to your firmware). That method is described in the ATmega328P datasheet, chapter 27.8 and is the primary method employed by "ISP programmer boards". You could use those from the Arduino IDE using the menu option "Upload using programmer".
If this "barebone Arduino" circuit is meant to use an ATmega328P with the Arduino bootloader, however, I would assume that JP4 is meant to provide a pin header for some SPI sensor module (even though you could program and even un-brick the chip using this interface).
NB: "FTDI" is a red herring here. One of the most-used ISP programmer boards employs an chip made by FTDI, so you could call this method "programming via FTDI" ... but a specific USB-to-Serial cable using an chip made by FTDI and an 1x5 pin header is also called an "FTDI cable". (For a while, FTDI made the best USB-to-Serial chips. Clones just did not work that reliable. Today, CH340G and CP2104 are reliable enough for hobby projects, but somehow, "FTDI" stuck as a name.)

Just adding https://docs.platformio.org/en/latest/platforms/atmelavr.html#upload-using-programmer for the platformio...

Thank you! I have one more question though. You said that JP4 is used for programming via an external programmer. However, I use the first pinout (JP2) with an external programmer (Sparkfun's Pocket AVR Programmer) that uses SPI communication protocol as an ISP (In System Programmer). So is there another protocol/interface being used with JP4?

@user1584421 That does not match the schematics you posted. JP2 and JP8 have the pins RXD und TXD, which points to an UART interface. JP4 has MISO, MOSI and SCK, which points to SPI interface. So either the schematics do not match the circuit you got in front of you, or you did use JP4 but remember using JP2, or the PocketAVR programmer has a method of detecting whether it should use UART or SPI that I don't know of (and is not described in its feature list).

The 2x2 pin JP2 is connected to the Atmel 16U2 or 32U2 processor (whichever the manufacturer used) which provides the USB I/O interface to/from the Atmel 328p, the one we usually consider to be the Uno's processor. When pins are actually installed on that pad, jumpers may be placed across either or both pairs to connect the xxU2's pin-4 to pin-6, and/or pin-5 to pin-7, which connect to that processor's interrupts (numbered the same as those pins).
My searches have not yielded any answer to the question of why it was provided, other than to suggest that they may have been intended for a feature that was never implemented. You can see JP2 and its connections to the xxU2 processor in the center of this schematic.
Update:
I was looking at the 3-pin connector(?) marked '???' in your question, and JP4 on the schematic in your update. Since your schematic does not show the xxU2 chip, and the connections of '???' are marked D11, D12, and D13, I'm going to guess instead that these are either auxilliary pins to access the 328's SPI interface, or is showing half of the ICSP hardware programming interface (the 3x2 pin block just above the '328 on the schematic I linked).

Thank you very much! I updated the question with the full schematic, if that is of any help to you.


text:
Provide custom AVR dude commands through the Arduino IDE
Besides the standard upload button that burns the code using FTDI, I want to then be able to provide custom AVRDude commands for burning fuses, when the external programmer is used.
Is this possible to do from the IDE? Maybe if I can edit some configuration files?
The idea is to have the IDE supply the upload command when the standard upload option is selected, but when external programmer is selected, i want to have custom behavior.
The custom behavior that I want is to preserve the EEPROM and set the lock bit.
These two actions can be performed with the following AVRDude commands:
avrdude -c usbtiny -p m328p -U hfuse:w:0xd2:m
avrdude -c usbtiny -p m328p -U lock:w:0x00:m

The external programmer i use is Sparkfun's "Pocket AVR Programmer" which is an SPI programmer.
So can I have custom behavior (supported by AVRDude) when I select program using external programmer?
EDIT:
I opened file boards.txt and i found these specifications of interest:
pro.name=Arduino Pro or Pro Mini

pro.upload.tool=avrdude
pro.upload.protocol=arduino

pro.bootloader.tool=avrdude
pro.bootloader.unlock_bits=0x3F
pro.bootloader.lock_bits=0x0F

pro.build.board=AVR_PRO
pro.build.core=arduino
pro.build.variant=eightanaloginputs

and
## Arduino Pro or Pro Mini (3.3V, 8 MHz) w/ ATmega328P
## ---------------------------------------------------
pro.menu.cpu.8MHzatmega328=ATmega328P (3.3V, 8 MHz)

pro.menu.cpu.8MHzatmega328.upload.maximum_size=30720
pro.menu.cpu.8MHzatmega328.upload.maximum_data_size=2048
pro.menu.cpu.8MHzatmega328.upload.speed=57600

pro.menu.cpu.8MHzatmega328.bootloader.low_fuses=0xFF
pro.menu.cpu.8MHzatmega328.bootloader.high_fuses=0xDA
pro.menu.cpu.8MHzatmega328.bootloader.extended_fuses=0xFD
pro.menu.cpu.8MHzatmega328.bootloader.file=atmega/ATmegaBOOT_168_atmega328_pro_8MHz.hex

pro.menu.cpu.8MHzatmega328.build.mcu=atmega328p
pro.menu.cpu.8MHzatmega328.build.f_cpu=8000000L

I am using Arduino Pro Mini.
In the second specification, there is the option for setting the fuse bits I want. However, there is no option for the lock bits.
The option for the lock bits are in the first specification - but there is no option for the fuses.
My new questions are these:

Should I specify the lock bits in the first specs and the fuses in the second? Will this work? I have to ask before trying anything stupid. Will the second specs "inherit" from the first specs?
Will the parameters I insert here only work for the Upload Using Programmer option? I want the regular upload (via bootloader) to work normally.
What happens if I ditch the Arduino platform and use a standalone AVR? If I use the same AVR that the Pro Mini platform had. Will the same settings work?

https://arduino.github.io/arduino-cli/0.27/platform-specification/#burn-bootloader or https://arduino.github.io/arduino-cli/0.27/platform-specification/#upload-using-an-external-programmer ?

Well, what i would like to be able to do is this: Preserve the EEPROM data, upload the program and then write the lock byte. There are three distinct AVRDude commands for performing these actions. I was wondering if i could modify the IDE, so that everytime you hit the upload button, it also preserves the EEPROM data and sets the lock byte.

I can't test it now, but you could add the fuse parameters to the tools.avrdude.program.pattern in platform.txt. Copy them from the tools.avrdude.erase.pattern. note: the fuse values are in boards.txt

So the tools.avrdude.program.pattern is what will happen when i program the arduino? And what are the contents of tools.avrdude.erase.pattern? What will the behaviour be after i copy them? I want three distinct steps (preserve EEPROM, upload, set lock bit). I updated the question with AVRDude commands, of what i am trying to achieve.

@Juraj I think I am getting closer. I edited the question. Could you please take a look at it? I have three sub-questions that are really quickly answered. Thank you very much!

those are not two specs in boards txt. all the pro.* keys values are applied, but some depend on the selection in CPU options in the Tools menu (like the fuses) while some are valid for all CPU options (lock bits)

@Juraj So if i use The Arduino Pro Mini, then it means i have to modify the first set for the lock bits, and the second set for the fuse values? Will this work? Also, does this work ONLY for the external programmer option?

you have to modify the tools.avrdude.program.pattern in platform.txt to add the parameter you want to be applied for "Upload with programmer". tools.avrdude.program.pattern is only for "Upload with programmer".

OK. These are its contents:tools.avrdude.program.pattern="{cmd.path}" "-C{config.path}" {program.verbose} {program.verify} -p{build.mcu} -c{protocol} {program.extra_params} "-Uflash:w:{build.path}/{build.project_name}.hex:i". Where and how exactly do i specify the lock bit and the fuses in there? I cannot find any reference on the internet, and the syntax is not obvious.

how is it not obvious? {cmd.path} is path to avrdude and those are parameters for avrdude, just the keys are not replaced with values. for pro mini it evaluates to avrdude -Cavrdude.conf -v -patmega328p -cusbtiny -Uflash:w:Blink.ino.hex:i

Thanks! Some parts are still not obvious. For example, how do I add a separator in the -U flag? I also want to pass hfuse:w:0xd2:m and lock:w:0x00:m. Finally, I should keep a copy of the original string, just in case I want to revert back to a normal operation. I mean, these are global settings, right?

as I already wrote, you can see the fuses parameters in  tools.avrdude.erase.pattern. you can copy from there

I know the fuse parameters, i have them in the question as well. I just don't know how to put them in the one liner on tools.avrdude.program.pattern. There are three parameters, fuses, lock bit and hex file. How do i separate them? What the correct command should be like?

and I say third time:  see the erase.pattern in platform.txt for the fuse parameters tools.avrdude.erase.pattern="{cmd.path}" "-C{config.path}" {erase.verbose} -p{build.mcu} -c{protocol} {program.extra_params} -e -Ulock:w:{bootloader.unlock_bits}:m -Uefuse:w:{bootloader.extended_fuses}:m -Uhfuse:w:{bootloader.high_fuses}:m -Ulfuse:w:{bootloader.low_fuses}:m

You said:
you have to modify the tools.avrdude.program.pattern in platform.txt to add the parameter you want to be applied for "Upload with programmer".
The parameters i want applied are
-U hfuse:w:0xd2:m -U lock:w:0x00:m
The erase params is what you just posted. You say this string should go to tools.avrdude.pattern.
I searched for example, for bootloader.high_fuses. These are in boards.txt. The values i found were not what i wanted. I want hfuse:w:0xd2. Where do i set this value? This is what i am asking.

so for a test modify boards.txt. what I don't know is if avrdude will apply these fuse parameters

Just did a test. In boards.txt, in the Pro Mini section, I changed pro.bootloader.lock_bits=0x0F to pro.bootloader.lock_bits=0x00 but unfortunately it didn't work, as I was able to read the flash. I guess it is not doable from inside the IDE.

it worked https://forum.arduino.cc/t/arduino-cannot-set-lock-bits-and-fuses-from-ide/1034159

You can add the fuse parameters to the "Upload using programmer" command pattern tools.avrdude.program.pattern in platform.txt. Copy them from the tools.avrdude.erase.pattern. (The fuse values are from boards.txt)
the modified upload command pattern:

tools.avrdude.program.pattern="{cmd.path}" "-C{config.path}" {program.verbose} {program.verify} -p{build.mcu} -c{protocol} {program.extra_params} "-Uflash:w:{build.path}/{build.project_name}.hex:i" -Ulock:w:{bootloader.lock_bits}:m

Is there a way to get the IDE to reload this file? I edit it and it seems like I need to close and reopen the IDE to get my changes to apply...

@ldoogy, yes, it requires to restart the IDE


text:
ArduinoMega2560 throws avrdude: com-state error after pressing the reset button a few times
I have recently switched to an ArduinoMega2560 (authentic) from the Arduino Uno and have been having a bit of trouble with uploading sketches after the reset button has been pressed a few times. This is the sketch I am using to test:
void setup() {
  Serial.begin(115200);
  Serial.println("hello world");
}

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

When I was using the Uno, the sketch would automatically run when the sketch is uploaded. When the reset button is pressed the sketch restarts ("hello world" is printed followed by "testing" every second). I can press the reset button any number of times and the sketch restarts with no issue. This is what I believe to be the expected behavior.
With the Mega however things have been unpredictable. When the sketch is uploaded it sometimes runs but other times not (haven't figured out the pattern if there is one) and after pressing the reset button it sometimes works, sometimes not. I have noticed that after the reset button a few times (3-5 times on average) then the following com-state error occurs:
avrdude: Version 6.3-20190619
         Copyright (c) 2000-2005 Brian Dean, http://www.bdmicro.com/
         Copyright (c) 2007-2014 Joerg Wunsch

         System wide configuration file is "C:\Users\Crustus\AppData\Local\Arduino15\packages\arduino\tools\avrdude\6.3.0-arduino17/etc/avrdude.conf"

         Using Port                    : COM3
         Using Programmer              : wiring
         Overriding Baud Rate          : 115200
avrdude: ser_open(): can't set com-state for "\\.\COM3"
avrdude: ser_drain(): read error: The handle is invalid.

avrdude: ser_send(): write error: sorry no info avail
avrdude: stk500_send(): failed to send command to serial port
avrdude: stk500v2_ReceiveMessage(): timeout
avrdude: ser_send(): write error: sorry no info avail
avrdude: stk500_send(): failed to send command to serial port
avrdude: stk500v2_ReceiveMessage(): timeout
avrdude: ser_send(): write error: sorry no info avail
avrdude: stk500_send(): failed to send command to serial port
avrdude: stk500v2_ReceiveMessage(): timeout
avrdude: ser_send(): write error: sorry no info avail
avrdude: stk500_send(): failed to send command to serial port
avrdude: stk500v2_ReceiveMessage(): timeout
avrdude: ser_send(): write error: sorry no info avail
avrdude: stk500_send(): failed to send command to serial port
avrdude: stk500v2_ReceiveMessage(): timeout
avrdude: ser_send(): write error: sorry no info avail
avrdude: stk500_send(): failed to send command to serial port
avrdude: stk500v2_ReceiveMessage(): timeout
avrdude: stk500v2_getsync(): timeout communicating with programmer

avrdude done.  Thank you.

Failed uploading: uploading error: exit status 1

If I try upload a sketch again after this it just times out.
Any idea what the issue could be? I have changed COM ports and tried but don't think it is a  COM port issue as the Uno works but perhaps that assumption is wrong.
Does the reset button work differently on the Uno and Mega perhaps?
I am using the ArduinoIDE (2.0.0-rc9.3).I have found a few instances of variations of this issue across the forums but have not found one resolved or relating to the reset button and it working intermittently.

try it with IDE 1. IDE 2 has still many problems. if it has the problem with IDE 1, return the Mega

@Juraj Thanks, I have tried IDE 1 and it has produced the same result

Are you testing this with nothing connected to the Mega board except the computer?

@timemage yes, nothing else connected

I am unable to replicate your problem using your code on an Arduino MEGA ADK, which is essentially the same board except having integrated USB host shield. Tested under Windows 10, IDE v1.8.9 as distributed from the Windows Store (v1.8.57.0), AVR boards package v1.8.5. You are resetting with just the reset button, right? Your board is not laying on top of a conductive surface would short when downward pressure was applied? Otherwise provide any other detail you can think might allow recreating the problem.

@timemage Thanks, appreciate the effort. I am resetting with the reset button and the board was not on a conductive surface - but good thing to note for future. Ended up reinstalling the IDE again and it seemed to fix it for now. IDE 2 still produces the same error (AVR v1.8.5) but IDE 1 (also AVR v1.8.5) works so guess I'll be going back to that. I am on Windows 11 so maybe something funky going on there. Thanks again.


text:
Motor with ultrasonic sensor
I am new to programming so bear with me.
I am writing a simple code to control a motor such that the motor will turn at full speed as long as the sensor does not detect an object within 5" of the sensor. If it does see something at 5 inches or less, then I want  to motor to stop.
My question is this: When using an IF statement, do you have to have the ELSE, or can you simply do two IF statements with no ELSE?
Here is my example:

int motorpin1 = 10 , motorpin2 = 11;
int trig = 12;
int echo = 9;
float distance;
float time;

void setup()
{
  pinMode (motorpin1, OUTPUT);
  //yellow wire
  pinMode (motorpin2, OUTPUT);
  //blue wire

  pinMode (trig, OUTPUT);
  pinMode (echo, INPUT);
  Serial.begin (9600);

}

void loop()
{
 // setup ultrasonic sensor to control
 //motor
  digitalWrite(trig, LOW);
  delayMicroseconds(2);
  digitalWrite(trig, HIGH);
  delayMicroseconds(10);
  digitalWrite(trig, LOW);
  time = pulseIn(echo, HIGH);
  distance = time/148.1;

  Serial.println(distance);

 if distance <5,digitalWrite (motorpin1, LOW);
 digitalWrite (motorpin2, LOW);

 if distance >=5, digitalWrite (motorpin1, HIGH);
 digitalWrite (motorpin2, LOW);
 delay (1000); //wait for 1 second

Is there a better way to do this with an ELSE statement? I want to capture the parameter where the code controls the specific parameters of >5  and then <or=5. Also, my next thing is to pause, and reverse the motor if after 1 second, the sensor still sees an object <=5.
Definitely a learning curve for this old brain of mine!

did you try to compile your code?

start thinking about if statements in your everyday life ... they happen all the time ... for example if (red light) {stop car}; ... then think if there would be an else block .... don't forget that you can put any command in the else block ... else if is useful

You can do something along the line of
if (distance < 5) {
    digitalWrite (motorpin1, LOW);
}
else {
    digitalWrite (motorpin1, HIGH);
}

It seems like you only set motorpin2 to LOW and never to HIGH. If you don't want to set it HIGH, move that line to the setup() section. There is no need to keep setting it LOW.

you could use a C++ ternary operator ... replace your six lines with one line ... digitalWrite (motorpin1, (distance < 5) ? LOW : HIGH );

@jsotola Well, if you're to bother going that route, the ternary operator is itself unnecessary: digitalWrite (motorpin1, !(distance < 5)); or just  digitalWrite (motorpin1, distance >= 5);

it depends on if HIGH is equal to true and LOW is equal to false

You could use a ternary operator and I do this myself, but since the question is asked by a beginner, I valued readability over reducing number of lines.

@jsotola, something considered and discarded. No one in their right mind will design a core with LOW as truthy an vice versa. Anyway, particularly for new people it's okay the way it is.


text:
Arduino filling serial buffer with nulls
I just wrote some code that just sends a string from Arduino to Processing.
Processing prints the string and displays the number of characters in the buffer...
After uploading the sketch to the Arduino and starting Processing for the first time, the serial buffer is initially filled with a few things (it turns out that these are nulls; 0 in ASCII). Why is this happening?
And this mostly happens after uploading and starting Processing for the first time. When I start Processing for the second time, the buffer is initially free as it should be. I am using a genuine Arduino Uno. I also tested on another Arduino and another laptop, but there is still the same problem. So it should not be a hardware problem.
Arduino Code
void setup() {
  Serial.begin(9600);
  //delay(1000)
  Serial.println("the quick brown fox jumps over the lazy dog");
  delay(1000);
}

void loop() {
}

Processing Code
import processing.serial.*;
Serial myPort;

void setup() {
  myPort = new Serial(this, "COM3", 9600);
}

void draw() {
  if (myPort.available()>0) {
    println("Buffer:"+myPort.available());
    String string = myPort.readStringUntil('\n');
    if (string!=null) {
      println("String:"+string);
    }
  }
}

In the image is other code just to show that the buffer contains nulls.

Is is an Arduino or an ESP? (Because the latter prints some data on boot, using a different baud rate, IIRC: 76800. This MAY result in nulls if you try to read them using a different baud rate than they're sent in, but usually results in garbage.)

I am using an Arduino Uno.

Not able to replicate your problem here with 1.8.19, avr core 1.8.5, processing 4.0.1, windows 10 and official UNO. Are you using something like a CH340 based clone?

The Arduino that I got is genuine not a clone.

Have you tried this myPort.bufferUntil(lf); in setup()? https://processing.org/reference/libraries/serial/Serial_bufferUntil_.html

There are a lot of these kind of questions on Stack Overflow (though I haven't seen this particular problem). Sample. Many solutions include catching exceptions (in Processing). A list of 347.

Does the Arduino restart when connected to?

Timing issues have been reported.

Provide versions numbers of everything involved like I did in explaining my attempt to replicate your problem.

versions are the same as yours.
Arduino 1.8.19,  Processing 4.0.1

What happens if you connect a 10 kOhm resistor from D1 to 5V?

If the problem is a matter of timing of the startup of the two microcontrollers on the Arduino Uno (e.g., the serial RX input is floating for some fraction of a second (or even more)), starting setup() with a pause of, say, 5 seconds, could alleviate the problem.

(On some Arduinos, e.g. Arduino Leonardo, the external pull-up resistor would not work there as it is for the second serial (hardware) port.)

@PeterMortensen that idea is part of why I asked the question. However I've since confirmed that the firmware for the Xu2 chip on the official UNO does in fact enable its internal pullup.

I tried connecting D1 to 5V but nothing changed

@PeterMortensen the Problem is alleviated by adding a 5 seconds delay before Serial.println(), but this makes the program slow.

In my tests, the only way I've been able to get anything approaching your sample output on an official UNO R3 is by pulling D1 toward ground strongly enough to cancel out the effect of the XU2's internal pullup. Do you have nothing besides the USB cable attached to your board when you're testing this? What kind of environment are you running this in? Have you tried a different computer? Have you tried a different UNO? Do see the exact same NUL characters if you use RealTerm?

@timemage I have nothing else connected to the board. I am using Arduino IDE 1.8.19.
I already tried the same code on a another arduino with another Computer. But those nulls still there. The number of NULL characters differes every time I upload the sketch. It is not the same number everytime.

Well, keep adding details. I'm able to recreate your test scenario in as far as it has been described, where the current answer to "Why is this happening?" is "It isn't." or at least "It isn't here." If you new details or a picture or something, I'll look at those and see if I'm replicating your setup accurately.

Re "by adding a 5 seconds delay before Serial.println(), but this makes the program slow.": No, I meant at startup, in setup(): A delay, before any set up of the serial hardware, as the very first statement / call. The 5 seconds is a very conservative number. It can successively be cut in half until the minimum required (empirically found) time has been found. It may only be 30 ms. But start with a very long time.

@timemage: I don't understand it either. I have now measured on a genuine Arduino R3 (not a clone) with a very weak pull-down resistor (1 MΩ - measured to 1.02 MΩ). The RX line was not asserted high until about 5 ms after the RESET signal went high (I measured 5.3 ms from RESET signal reached 2.0 V till RX went high). But a very simple sketch where the very first action in setup() was to set D12 to output and then high took a whopping 1.5 seconds (I measured 1.56 seconds), about 300 times longer. The Arduino was powered through the USB cable (and connected to a Linux system).

I also verified the 1.5 seconds with a stopwatch, by setting D13 (LED) high immediately after D12. I measured about 1.8 seconds from power on till the LED lit up. With reaction time, about 0.3 seconds, 1.5 seconds is about right.

Is there a way for setup() to execute sooner?

Related: What happens on Arduino power-on, and how long does it all take?. 1.544 seconds was measured on an Arduino Uno R2. Start your Arduino instantly - no boot time without bootloader

OK, I got it the wrong way around. Robot12, what is the exact startup sequence of the two systems, the Processing program and the Arduino, (incl. approximate timing)? For instance, is the Processing program running while the Arduino is being programmed? What do you actually do? Can you add the steps/the procedure to the question?

If connecting to the COM port from Processing results in a RESET on the Arduino then the TX line could be floating for a number of milliseconds.

Only the first COM port connect/open after power on of the Arduino results in a RESET (at least on Linux, using 'Screen' as the serial monitor), pulse width about 600 µsec if a 2.0 V threshold is used (but it is a ill-defined RESET signal, RC charge up on the rising edge). Thus the system has a state on which the observed behaviour may depend on: 1) Connected to once. 2) Connected to more than once.

Further, TX does not change during such a "soft" RESET by connection, only during power up. The timing during power up for TX is similar to RX: TX is asserted high 5.2 ms after RESET becomes 2.0 V.

Correction: "... has a state ...  1) Never connected to. 2) Connected to one or more times.

(And the "soft" RESET by connection actually has an effect: the D12 control signal is unasserted (input) for 1.51 seconds, as expected.)

I'm not sure I'm going to be able to follow all of what you've said above now. But regarding the part you addressed me about "The RX line was not asserted high until about 5 ms after", the thing I was testing was the transceivers RX (AVR's TX) because that's what's in play here. And that may well float for 5ms during power-on of the transceiver. However transceiver is also not trying to receive anything during that time, so it hardly matters. I ignored the other direction for a number of reasons, most of it related to fact that the first example doesn't read anything at all on the AVR.

@Robot12: Did you make progress?

sorry for the delay responding. I just ignored these Nulls and kept working on my project.


text:
ArduinoJSON :: How to determine Array's size in a DOC conatinaing not only Arrays
Parameter file containing MQTT topics as shown below, is read into StaticJsonDocument<1250> DOC variable.
Size of some groups may differ between MCU's, for example sub_topics_win may contain more topics, if MCU is 8 relay unit. For that I need the flexibility to read a specific topic that can differ in size.
What is the rifht way to do it?
{
    "pub_gen_topics": [
        "myHome/Messages",
        "myHome/log",
        "myHome/debug"
    ],
    "pub_topics": [
        "myHome/Cont_A/Avail",
        "myHome/Cont_A/State"
    ],
    "sub_topics": [
        "myHome/Cont_A",
        "myHome/All",
        "myHome/lockdown"
    ],
    "sub_topics_win": [
        "myHome/Windows/gFloor/TwinWindow",
        "myHome/Windows/gFloor/Pergola"
    ],
    "sub_topics_SW": [
        "myHome/Light/int/gFloor/SalAmbient1",
        "myHome/Light/int/gFloor/SalAmbient2",
        "myHome/Light/int/gFloor/Lobby",
        "myHome/Light/int/gFloor/Corridor"
    ],
    "sub_topics_win_g": [
        "myHome/Windows",
        "myHome/Windows/gFloor"
    ],
    "sub_topics_SW_g": [
        "myHome/Light",
        "myHome/Light/int",
        "myHome/Light/int/gFloor/"
    ],
    "ver": 0.1
}

https://arduinojson.org/v6/api/jsonarray/size/

@Juraj I tried to define DOC["pub_gen_topics"], for example, as an array and using size() to get its size, without any luck.

add some code to the question

If your question is How can I read each element of an array when I don't know its size?, then simply use a for-loop, like so:
JsonArray sub_topics_win = doc["sub_topics_win"];

for (const char* topic : pub_gen_topics) {
  Serial.println(topic);
}

See also: JsonArray::begin() / end(), JsonArray::size().

An early try was JsonArray array = DOC["sub_topic_win"].to<JsonArray>();. I tried to create it as an Array by adding .to<JsonArray>()

to<JsonArray>() creates an empty array, as<JsonArray>() casts the value to a JsonArray, allowing you to use the for-loop.

As I understand, your question is How can I determine the best capacity for a JsonDocument when my input varies?
If that's the case, I recommend that you read How to determine the capacity of the JsonDocument?. Here is an extract from the section "What if my input varies?":

If your program must deserialize a JSON document that changes, you must allocate a JsonDocument that is large enough for the largest valid input. I insist on the term valid because your program doesn't need to support any JSON document, but only the ones relevant to your use case.

Applying this to your problem, you need to put eight topics in each list and pass this document to the ArduinoJson Assistant, which results in a recommended capacity of 3027 bytes on ESP8266. Now, this is a bit large for a StaticJsonDocument, so consider switching to a DynamicJsonDocument.

Sorry for not explaining myself good enough.  Input, as show in my question is considered to be suited in  size of 1250. But there is a real life situation that "sub_topics_win" would be consisted of 8 elements and not 2 as shown.
When array size is known (2 in show case) I use a for loop of 2 iterations to read that array. And my question is - how can I read an array when is size can vary ?


text:
ATTiny84 I2C with NeoPixels not working
I fetch RGB values via I2C - which works (with a splitting function).
Now I have a problem:

When I write values directly into strip.color() like strip.Color(255,0,0,0) the NeoPixels turn red when receiving the values.
When I use the values from the I2C connection it won't work anymore. But the values are correct if I have a look in the Serial Monitor.

Maybe the data type is wrong or something?
#include <Wire.h>
#include <Adafruit_NeoPixel.h>

#define LED_PIN   4
#define LED_COUNT 4

static const int SLAVE_ADDRESS = 0x08;

uint32_t currentColor;
int currentBrightness = 50;
int flashState = 0;
String ledRed, ledGreen, ledBlue, ledWhite;

String temp;
String payload;

Adafruit_NeoPixel strip(LED_COUNT, LED_PIN, NEO_GRBW + NEO_KHZ800);

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

  strip.begin();
  strip.show(); // Turn off all pixels asap
  strip.setBrightness(50); // Set brightness

  pinMode(3, OUTPUT);
  digitalWrite(3, HIGH);

  Wire.begin(SLAVE_ADDRESS);
  Wire.onReceive(change);
}

// Set all pixels to color
void setPixelColors(uint32_t color) {
  for(int p = 0; p < LED_COUNT; p++) {
    strip.setPixelColor(p, color);
  }
  strip.show();

  delay(1000);
  digitalWrite(3, HIGH);
}

// Split the I2C message
String split(String s, char parser, int index) {
  String rs="";
  int parserIndex = index;
  int parserCnt=0;
  int rFromIndex=0, rToIndex=-1;
  while (index >= parserCnt) {
    rFromIndex = rToIndex+1;
    rToIndex = s.indexOf(parser,rFromIndex);
    if (index == parserCnt) {
      if (rToIndex == 0 || rToIndex == -1) return "";
      return s.substring(rFromIndex,rToIndex);
    } else parserCnt++;
  }
  return rs;
}

void loop() {
  // ...
}

void change(int howMany) {
  digitalWrite(3, LOW);
  temp = "";
  if (Wire.available()) {
    // Fetch the string
    while(Wire.available()) {
      char c = Wire.read();
      temp.concat(c);
    }

    payload = String(temp);
    flashState = split(payload, ',', 0).toInt();
    ledRed = split(payload, ',', 1);
    ledGreen = split(payload, ',', 2);
    ledBlue = split(payload, ',', 3);
    ledWhite = split(payload, ',', 4);

    byte bufRed[3];
    ledRed.toCharArray(bufRed, 3);

    byte bufGreen[3];
    ledGreen.toCharArray(bufGreen, 3);

    byte bufBlue[3];
    ledBlue.toCharArray(bufBlue, 3);

    byte bufWhite[3];
    ledWhite.toCharArray(bufWhite, 3);

    //setPixelColors(strip.Color(255, 0, 255, 0)); // WORKING

    currentColor = strip.Color(bufRed, bufGreen, bufBlue, bufWhite);
    setPixelColors(currentColor); // NOT WORKING
  }

  // Proof the I2C reading is finished
  delay(10);
}

I tried different data types, attached a status LED so I know it the I2C connection is working. When I test it with my UNO I get for R=255 G=0 B=255 W=0; like intended.
"Fun fact": On my UNO it works like a charm. It's just the ATTiny85 that won't accept that values(?)

New Code:
#include <Wire.h>
#include <Adafruit_NeoPixel.h>

#define LED_PIN   4
#define LED_COUNT 20

static const int SLAVE_ADDRESS = 0x08;

int currentBrightness = 50;
int flashState = 0;
int ledRed, ledGreen, ledBlue, ledWhite;

volatile bool recvFlag = false;
volatile uint32_t currentColor = 0;
String temp;

String payload;

Adafruit_NeoPixel strip(LED_COUNT, LED_PIN, NEO_GRBW + NEO_KHZ800);

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

  strip.begin();
  strip.show(); // Turn OFF all pixels ASAP
  strip.setBrightness(50); // Set BRIGHTNESS to about 1/5 (max = 255)

  Wire.begin(SLAVE_ADDRESS);
  Wire.onReceive(change);
}

void setPixelColors(uint32_t color) {
  for (int p = 0; p < LED_COUNT; p++) {
    strip.setPixelColor(p, color);
    strip.show();
  }
}

String split(String s, char parser, int index) {
  String rs = "";
  int parserIndex = index;
  int parserCnt = 0;
  int rFromIndex = 0, rToIndex = -1;
  while (index >= parserCnt) {
    rFromIndex = rToIndex + 1;
    rToIndex = s.indexOf(parser, rFromIndex);
    if (index == parserCnt) {
      if (rToIndex == 0 || rToIndex == -1) return "";
      return s.substring(rFromIndex, rToIndex);
    } else parserCnt++;
  }
  return rs;
}

void loop() {
  if (recvFlag) {
    payload = String(temp);
    flashState = split(payload, ',', 0).toInt();
    ledRed = split(payload, ',', 1).toInt();
    ledGreen = split(payload, ',', 2).toInt();
    ledBlue = split(payload, ',', 3).toInt();
    ledWhite = split(payload, ',', 4).toInt();

    currentColor = strip.Color(ledRed, ledGreen, ledBlue, ledWhite);
    setPixelColors(currentColor);

    recvFlag = false;
  }
}

void change(int howMany) {
  temp = "";
  if (Wire.available()) {
    // Fetch the string
    while (Wire.available()) {
      char c = Wire.read();
      temp.concat(c);
    }

    // Proof the I2C reading is finished
    recvFlag = true;
  }
}

Honestly I don't know, why exactly this works on your Uno. You need to know, that the onReceive callback function is called from an ISR (Interrupt Service Routine). And inside an ISR you cannot do things, that rely on interrupts to work (like delay()), since only one interrupt can run at a time. I'm not sure, how the Neopixel library works in its core, but its probably not a good idea to run the show() method inside an ISR. Also generally you don't want to do long things inside an ISR, since it will block all the other interrupt powered functions of your microcontroller (for example I2C, Serial, time keeping via delay() or millis()...).
Instead the best practice is to only set a flag and then do these things in the main code (aka in loop()). So something like this:
volatile bool recv_flag = false;
volatile uint32_t current_color = 0;

void setup(){
    // Initiating everything like you already did in your code
    ...
}

void loop(){
    if(recv_flag){
        setPixelColors(currentColor);
        recv_flag = false;
    }
}
void change(int howMany) {
  digitalWrite(3, LOW);
  temp = "";
  if (Wire.available()) {
    // Doing all the data parsing like you already did
    ...
    // save current color in global variable
    currentColor = strip.Color(bufRed, bufGreen, bufBlue, bufWhite);
    // set flag
    recv_flag = true;
  }
}

Note that every variable, that will be written to inside an ISR should be declared as volatile. This prevents the compiler from optimizing it out, since it cannot know when the interrupts will happen. So it might think that this variable will never change and just replace it with a literal. The volatile keyword prevents that.

As mentioned above I'm even wondering, why your code works on the Uno. Though the main difference between the Uno and the Attiny84 is, that the Uno as a full fledged I2C hardware interface, while the Attiny84 only has an USI (Universal Serial interface). So the Uno has most of the I2C communication implemented in hardware, while the Attiny84 needs to run (probably interrupt based) code to do the communication.

I got it to work very shortly with 4 LEDs. Thought that was it. But then I tried with 20 LEDs - nothing happend again. I tried the example with "colorWipe" from the library. This works - so there is enough power and every LED is working.... And my API+Splitting has be working to because it worked for 2-3 tests before adding more LEDs. Any other ideas why THIS is happening now? :/

@dessi You can add the new code to your question. Then I will see, if I can help you with that. But please leave the current question text intact, so that others can learn from it

just updated the question with the new code

@dessi All in all your code looks good. You should declare temp as volatile, since you are writing to it inside the ISR. But I don't think this is the issue. Can you be sure, that the I2C communication works like intended? For example by lighting and LED, of the correct data was received? And can you check, if the code blocks at some point? If yes, where exactly does it block? Or does the code run, but it has no effect? That would be important information to debug further.

Maybe you get an issue with all the String use. It used dynamic memory allocation, which can make swiss cheese out of your memory (for reference Majenkos blog entry about this. Though that should only be a problem after some more I2C transactions.

Hey buddy, I just gave up... I'll do it now another way. I can transfer one single character without a problem so I'm pulling a value char of a custom matrix with me and have fixed LED values on the ATTiny85 :/ Project is a bit time critical so I have to fix that values :/ But thank you for your help anyway! Maybe someday some one needs the volatile stuff :)


text:
Is my nrf24l01 radio module broken?
I was trying to use two Arduino Nano connected to two RF24 modules to build a remote control boat. I self-assembled both the remote and the receiver circuit following the skematic suggested in that page (NRF24 and Arduino Nano Every usage).
VCC - 5V (via adapter)
GND - GND
10 pin - CE
A3 - CSN
11 pin - MOSI
12 pin - MISO
13 pin - SCK
not connected - IRQ
(I double and triple checked that I connected all the cables as in the skematic)
Then, as always suggested in the link above, I checked my connection using that sketch:
#include <SPI.h>
#include <nRF24L01.h>
#include <RF24.h>

RF24 radio(10,A3);  // for arduino nano every
//RF24 radio(9,10); // for arduino uno

const uint8_t num_channels = 128;
uint8_t values[num_channels];
void setup(void)
{
  Serial.begin(9600);
  printf_begin();
  radio.begin();
  radio.setAutoAck(false);
  radio.startListening();

  radio.printDetails();
  delay(5000);

  radio.stopListening();
  int i = 0;
  while ( i < num_channels )  {
    printf("%x",i>>4);
    ++i;
  }
  printf("\n\r");
  i = 0;
  while ( i < num_channels ) {
    printf("%x",i&0xf);
    ++i;
  }
  printf("\n\r");
}
const int num_reps = 100;

void loop(void)
{
  memset(values,0,sizeof(values));
  int rep_counter = num_reps;
  while (rep_counter--) {
    int i = num_channels;
    while (i--) {
      radio.setChannel(i);
      radio.startListening();
      delayMicroseconds(128);
      radio.stopListening();
      if ( radio.testCarrier() )
        ++values[i];
    }
  }
  int i = 0;
  while ( i < num_channels ) {
    printf("%x",min(0xf,values[i]&0xf));
    ++i;
  }
  printf("\n\r");
}
int serial_putc( char c, FILE * ) {
  Serial.write( c );
  return c;
}

void printf_begin(void) {
  fdevopen( &serial_putc, 0 );
}

And that's what I found for the RX:
STATUS       = 0xff RX_DR=1 TX_DS=1 MAX_RT=1 RX_P_NO=7 TX_FULL=1
RX_ADDR_P0-1     = 0xffffffffff 0xffffffffff
RX_ADDR_P2-5     = 0xff 0xff 0xff 0xff
TX_ADDR      = 0xffffffffff
RX_PW_P0-6   = 0xff 0xff 0xff 0xff 0xff 0xff
EN_AA        = 0xff
EN_RXADDR    = 0xff
RF_CH        = 0xff
RF_SETUP     = 0xff
CONFIG       = 0xff
DYNPD/FEATURE    = 0xff 0xff
Data Rate    = 1MBPS
Model        = nRF24L01
CRC Length   = 16 bits
PA Power     = PA_MAX
00000000000000001111111111111111222222222222222233333333333333334444444444444444555555555555555566666666666666667777777777777777

0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef

So that means the RF24 module isn't connected properly to the board, the correct output in the second line would be something like that: RX_ADDR_P0-1 = 0xf0f0f0f0d2 0xc2c2c2c2c2
I used a tester to check the power supply and the antenna receives 3.3V as it should.
I checked also the soldering and I didn't find any poor connections nor short circuits.
I tried all the analog pins between the A0 and A5 for the CSN for perhaps the A3 was not working.
Well, now I ran out of ideas and I'm tempted to think that my radio module is broken, but maybe I overlooked something, can you please write any ideas that you think could help?
Thankyou in advance

this may help ... https://duckduckgo.com/?q=arduino+nrf24l01+hello+world&ia=qa


text:
Deserialization error arduino uno and nodemcu esp8266 to Thingspeak
I am currently sending temperature and humidity readings to a Thingspeak channel via a nodemcu esp8266 wifi module using serial communication between the arduino and esp. I have set the time between sending data to Thingspeak to 30s, however the time stamps I receive on my Thingspeak channel are very inconsistent even though the data has been supposedly sent (ranging from 3 minutes to 15 minutes). I suspect this could be due to some timing error as I receive many deserialization errors when I convert the Json string (deserialize it on the NodeMCU side). Any help would be appreciated! Note, this is only a part of the project, there are multiple relays added, thus using the nodemcu on its own would be insufficient. I have also added some images, which shows the outputs.
Arduino Uno code:
//Arduino side code
#include <DHT.h>

#include <avr/wdt.h>                //Watchdog Timer

#include <SoftwareSerial.h>         //Arduino to NodeMCU Lib
#include <ArduinoJson.h>

SoftwareSerial nodemcu(5, 6);       //Initialise Arduino to NodeMCU (5=Rx & 6=Tx)

//Initialisation of DHT22 Sensor
#define DHTPIN 4
DHT dht(DHTPIN, DHT22);
float tempC;
float humidity;
float VPD;

void setup() {
  Serial.begin(9600);
  dht.begin();
  nodemcu.begin(9600);
  delay(2000);

  wdt_enable(WDTO_4S);              //Enable Watchdog timer

  Serial.println("Program started");
}

void loop() {
  StaticJsonDocument<1000> doc;

  dht22_func();                          //Obtain Temp and Hum data

  doc["humidity"] = humidity;            //Assign collected data to JSON Object
  doc["temperature"] = tempC;
  doc["VPD"] = VPD;

  serializeJson(doc, nodemcu);           //Send data to NodeMCU

  wdt_reset();                           //Reset for WDT
}

void dht22_func() {

  humidity = dht.readHumidity();
  tempC = dht.readTemperature();
  Serial.print("Humidity: ");
  Serial.println(humidity);
  Serial.print("Temperature: ");
  Serial.println(tempC);

  if (isnan(humidity) || isnan(tempC) || humidity == 0.0 || tempC == 0.0) {
    while (1) {}
  }
}

NodeMCU code:
#include <SoftwareSerial.h>
#include <ArduinoJson.h>

#include <ESP8266WiFi.h>
#include <ThingSpeak.h>

SoftwareSerial nodemcu(D6, D5);                 //D6 = Rx & D5 = Tx

unsigned long previousMillis = 0;
unsigned long currentMillis;
const unsigned long period = 10000;             //Upload interval in ms

float tempC;
float humidity;
float VPD;

String apiKey = "";             //Write API key

unsigned long channelID = ;              //Thingspeak channel ID
const char *ssid =  "";             //Local network ssid
const char *pass =  "";                 //Local network password
const char* server = "api.thingspeak.com";      //Thingspeak server

boolean state1 = false;                         //Boolean variables
boolean state2 = false;

WiFiClient client;

void setup() {
  Serial.begin(9600);
  nodemcu.begin(9600);
  ThingSpeak.begin(client);
  while (!Serial) continue;
  delay(2000);

  Serial.println("Program Started");

  wifi_connect();                                      //Establish wifi connection
}

void loop() {
  currentMillis = millis();                                  //Get current time

  if ((currentMillis - previousMillis >= period)) {

    if (WiFi.status() != WL_CONNECTED) {                    //Check if connected to wifi, else
connect
      wifi_connect();
}
else {
  Serial.println("Currently Connected to WiFi");
}

while (state1 == false) {                                //Connect to Thingspeak and push data

  while (state2 == false) {
    parseJsonObject();
  }

  cloud_connect();
}

state1 = false;
state2 = false;
Serial.println("Cloud Connect Succesful");
Serial.println("-----------------------------------------");
previousMillis = previousMillis + period;                     //Update counter
  }
}

void wifi_connect() {
  Serial.println("Connecting to ");
  Serial.println(ssid);

  WiFi.begin(ssid, pass);

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

void cloud_connect() {
  if (client.connect(server, 80)) {           //80 is the standard port number used for web access
    String postStr = apiKey;
    postStr += "&field1=";
    postStr += String(tempC);
    postStr += "&field2=";
    postStr += String(humidity);
    postStr += "\r\n\r\n";

    client.print("POST /update HTTP/1.1\n");
    client.print("Host: api.thingspeak.com\n");
    client.print("Connection: close\n");
    client.print("X-THINGSPEAKAPIKEY: " + apiKey + "\n");
    client.print("Content-Type: application/x-www-form-urlencoded\n");
    client.print("Content-Length: ");
    client.print(postStr.length());
    client.print("\n\n");
    client.print(postStr);

    Serial.print("Temperature: ");
    Serial.print(tempC);
    Serial.print(" || Humidity: ");
    Serial.println(humidiy);
    Serial.println("Sent to Thingspeak");

    //Change state to true to break while loop
  state1 = true;
  }
  client.stop();
}

void parseJsonObject() {
  //Parse JSON object from serial port
  StaticJsonDocument<1000> doc;
  DeserializationError error = deserializeJson(doc, nodemcu);

  // Test if parsing succeeds
  if (error) {
    Serial.println("deserializeJson error");
    return;
  }

  //Parse Json values and store in variable
  humidity = doc["humidity"];
  tempC = doc["temperature"];

  if (isnan(humidity) || isnan(tempC) || humidity == 0.0 || tempC == 0.0) {
    Serial.println("Invalid Sensor Readings");
    return;
  }

  state2 = true;
  Serial.println("JSON Object Recieved");
}

try much less than 1000 bytes for StaticJsonDocument

How would this help? I'm quite a newbee to the javascript file format.

Uno has only 2000 bytes of SRAM

How much would be required for this application? Thank you for the response

I guess 200 should be enough. https://arduinojson.org/v6/assistant/

Thank you. This has shortened the intervals between uploads to Thingspeak, however the main problem of the deserilization of the json file is still evident (inconsistent intervals) . Any possible suggestions on this? I think most of the strings the nodemcu sends to the cloud might be "broken" - not the correct format, probably due to some timing error.

so a simplest patch would be to add at the beginning of parseJsonObject line while (nodemcu.peek() != '{') nodemcu.read(); to 'sync' the input to the beginning of the simple json you send from Uno so the deserializeJson doesn't start in the middle of the json (the Uno sends them without a pause)

Thingspeak supports multiple fields in one transaction so it may not be necessary to pack the data into a json string if you are sending only temperature and humidity value every 30 seconds or so.

@6v6gt json is send between uno and esp8266

thank you @juraj , I will try that now and let you know!

@juraj thank you so much. Massively improved the intervals and consistency between uploads. Regards!