text:
Equivalent libary of RTCZero for Arduino UNO
I am a beginner to Ardunino UNO
This is my first program to light up an LED strip
#include <Adafruit_NeoPixel.h>

#include <RTCZero.h>

#define PIN            6
#define NUMPIXELS      60 // Define the total number of pixels in your strip
#define BRIGHTNESS     50 // Adjust the brightness (0-255)

Adafruit_NeoPixel strip = Adafruit_NeoPixel(NUMPIXELS, PIN, NEO_GRB + NEO_KHZ800);
RTCZero rtc;

void setup() {
  strip.begin(); // Intializes the neo pixel library for use
  strip.show();  // Initialize all pixels to 'off'

  rtc.begin();
// Intialzes the real time clock , the rtc is defined previuosly ,the dot access the the memebr in this case begin () , which is a method , method is used to perform an action , they belong to a class and defines how an object behaves

  // Set the initial time at the time of the project
  rtc.setHours(12);
  rtc.setMinutes(0);
  rtc.setSeconds(0);
}

void loop() {

  int currentHour = rtc.getHours(); // Get the current hour from the real time clock
  uint32_t color;

  // Set color based on the time of the day
  if (currentHour >= 6 && currentHour < 16) {
    // Yellow during 6 am to 4 pm

    color = strip.Color(255, 255, 0);
  } else if (currentHour >= 16 && currentHour < 20) {
    // Orange during 4 pm to 8 pm

    color = strip.Color(255, 165, 0);
  } else {
    // Blue during 8 pm to 6 am

    color = strip.Color(0, 0, 255);
  }

  // Set the color for all pixels
  fillStrip(color);

  // Optional: Adjust brightness
  strip.setBrightness(BRIGHTNESS);

  // Update the NeoPixel strip
  strip.show();

  // Delay to avoid updating the colors too frequently
  delay(60000); // Delay for 1 minute (adjust as needed)
}

// Uses for loop to itrate the color for all the pixels in the led strip
void fillStrip(uint32_t color) {
  for (int i = 0; i < strip.numPixels(); i++) {
    strip.setPixelColor(i, color);
  }
}

Unable to compile the program due to the below error.
How do I find an equivalent function for Arduino UNO ??
WARNING: library RTCZero claims to run on samd architecture(s) and may be incompatible with your current board which runs on avr architecture(s).

The RTCZero library is meant to control the RTC peripheral embedded in some Arduinos. The Uno does not have an embedded RTC, so there can be no equivalent.

There is no built in RTC on a normal Arduino UNO.  If you want to do the same thing on an UNO you can either add an external RTC module like the DS3231 or the DS1307.  There are libraries in the library manager for those devices that will work with your UNO.  You can then find the functions that perform the same job as the ones in your code and replace them.
If your UNO is the new UNO-R4, then yes those do have an RTC and there is a library in the core for it, but the RTC on those boards is terribly inaccurate due to the lack of an accurate clock source to drive it.  So even in that case I'd still recommend an external RTC.


text:
DigiKeyboard BIOS Compatibility
I am using a custom version of the DigiKeyboard library, to use a Digispark as a keyboard in the BIOS. It works on most computers, but HP 730 Thin clients dont recognize it as a keyboard.
Below is the custom version. Any suggestions on how to fix this issue? Thank you in advance for any suggestions/help.
/*
 * Based on Obdev's AVRUSB code and under the same license.
 *
 * TODO: Make a proper file header. :-)
 * Modified for Digispark by Digistump
 */
#ifndef __DigiKeyboard_h__
#define __DigiKeyboard_h__

#include <Arduino.h>
#include <avr/pgmspace.h>
#include <avr/interrupt.h>
#include <avr/delay.h>
#include <string.h>

#include "usbdrv.h"
#include "scancode-ascii-table.h"

// TODO: Work around Arduino 12 issues better.
//#include <WConstants.h>
//#undef int()

typedef uint8_t byte;

#define BUFFER_SIZE 2 // Minimum of 2: 1 for modifiers + 1 for keystroke

static uchar    idleRate;           // in 4 ms units

/* Boot protocols have been added.
 * We do allow simultaneous key presses.
 * The report descriptor has been created with usb.org's "HID Descriptor Tool"
 * which can be downloaded from http://www.usb.org/developers/hidpage/.
 * Redundant entries (such as LOGICAL_MINIMUM and USAGE_PAGE) have been omitted
 * for the second INPUT item.
 */
const PROGMEM uchar usbHidReportDescriptor[USB_CFG_HID_REPORT_DESCRIPTOR_LENGTH] = { /* USB report descriptor */
        0x05, 0x01, // USAGE_PAGE (Generic Desktop)
        0x09, 0x06, // USAGE (Keyboard)
        0xa1, 0x01, // COLLECTION (Application)
        0x05, 0x07, // USAGE_PAGE (Keyboard)
        0x19, 0xe0, // USAGE_MINIMUM (Keyboard LeftControl)
        0x29, 0xe7, // USAGE_MAXIMUM (Keyboard Right GUI)
        0x15, 0x00, // LOGICAL_MINIMUM (0)
        0x25, 0x01, // LOGICAL_MAXIMUM (1)
        0x75, 0x01, // REPORT_SIZE (1)
        0x95, 0x08, // REPORT_COUNT (8)
        0x81, 0x02, // INPUT (Data,Var,Abs)
        0x95, 0x01, // REPORT_COUNT (1)
        0x75, 0x08, // REPORT_SIZE (8)
        0x81, 0x03, // INPUT (Cnst,Var,Abs)
        0x95, 0x05, // REPORT_COUNT (5)
        0x75, 0x01, // REPORT_SIZE (1)
        0x05, 0x08, // USAGE_PAGE (LEDs)
        0x19, 0x01, // USAGE_MINIMUM (Num Lock)
        0x29, 0x05, // USAGE_MAXIMUM (Kana)
        0x91, 0x02, // OUTPUT (Data,Var,Abs)
        0x95, 0x01, // REPORT_COUNT (1)
        0x75, 0x03, // REPORT_SIZE (3)
        0x91, 0x03, // OUTPUT (Cnst,Var,Abs)
        0x95, 0x06, // REPORT_COUNT (6)
        0x75, 0x08, // REPORT_SIZE (8)
        0x15, 0x00, // LOGICAL_MINIMUM (0)
        0x25, 0x65, // LOGICAL_MAXIMUM (101)
        0x05, 0x07, // USAGE_PAGE (Keyboard)
        0x19, 0x00, // USAGE_MINIMUM (Reserved (no event indicated))
        0x29, 0x65, // USAGE_MAXIMUM (Keyboard Application)
        0x81, 0x00, // INPUT (Data,Ary,Abs)
        0xc0 // END_COLLECTION
};

/* Keyboard usage values, see usb.org's HID-usage-tables document, chapter
 * 10 Keyboard/Keypad Page for more codes.
 */
#define MOD_CONTROL_LEFT    (1<<0)
#define MOD_SHIFT_LEFT      (1<<1)
#define MOD_ALT_LEFT        (1<<2)
#define MOD_GUI_LEFT        (1<<3)
#define MOD_CONTROL_RIGHT   (1<<4)
#define MOD_SHIFT_RIGHT     (1<<5)
#define MOD_ALT_RIGHT       (1<<6)
#define MOD_GUI_RIGHT       (1<<7)

#define KEY_A       4
#define KEY_B       5
#define KEY_C       6
#define KEY_D       7
#define KEY_E       8
#define KEY_F       9
#define KEY_G       10
#define KEY_H       11
#define KEY_I       12
#define KEY_J       13
#define KEY_K       14
#define KEY_L       15
#define KEY_M       16
#define KEY_N       17
#define KEY_O       18
#define KEY_P       19
#define KEY_Q       20
#define KEY_R       21
#define KEY_S       22
#define KEY_T       23
#define KEY_U       24
#define KEY_V       25
#define KEY_W       26
#define KEY_X       27
#define KEY_Y       28
#define KEY_Z       29
#define KEY_1       30
#define KEY_2       31
#define KEY_3       32
#define KEY_4       33
#define KEY_5       34
#define KEY_6       35
#define KEY_7       36
#define KEY_8       37
#define KEY_9       38
#define KEY_0       39

#define KEY_ENTER   40

#define KEY_SPACE   44

#define KEY_F1      58
#define KEY_F2      59
#define KEY_F3      60
#define KEY_F4      61
#define KEY_F5      62
#define KEY_F6      63
#define KEY_F7      64
#define KEY_F8      65
#define KEY_F9      66
#define KEY_F10     67
#define KEY_F11     68
#define KEY_F12     69

#define KEY_LEFT        0x50
#define KEY_RIGHT     0x4F
#define KEY_DOWN        0x51
#define KEY_UP          0x52
#define KEY_DEL         0x4C
#define KEY_TAB       0x2B
#define KEY_BACKSP    0x2A
#define KEY_TILDE     0x35
#define KEY_MINUS     0x2D
#define KEY_EQUAL     0x2E
#define KEY_L_BRACE   0x2F
#define KEY_R_BRACE   0x30
#define KEY_BACKSLASH 0x31
#define KEY_SEMICOLON 0x33
#define KEY_QUOTE     0x34
#define KEY_COMMA     0x36
#define KEY_PERIOD    0x37
#define KEY_SLASH     0x38

#define KEY_ESC       0x29

class DigiKeyboardDevice : public Print {
 public:
  DigiKeyboardDevice () {
    cli();
    usbDeviceDisconnect();
    _delay_ms(250);
    usbDeviceConnect();

    usbInit();

    sei();

    // TODO: Remove the next two lines once we fix
    //       missing first keystroke bug properly.
    memset(reportBuffer, 0, sizeof(reportBuffer));
    usbSetInterrupt(reportBuffer, sizeof(reportBuffer));
  }

  void update() {
    usbPoll();
  }

    // delay while updating until we are finished delaying
    void delay(long milli) {
        unsigned long last = millis();
      while (milli > 0) {
        unsigned long now = millis();
        milli -= now - last;
        last = now;
        update();
      }
    }

  //sendKeyStroke: sends a key press AND release
  void sendKeyStroke(byte keyStroke) {
    sendKeyStroke(keyStroke, 0);
  }

  //sendKeyStroke: sends a key press AND release with modifiers
  void sendKeyStroke(byte keyStroke, byte modifiers) {
    sendKeyPress(keyStroke, modifiers);
  delay(10);
    // This stops endlessly repeating keystrokes:
    sendKeyPress(0,0);
  }

  //sendKeyPress: sends a key press only - no release
  //to release the key, send again with keyPress=0
  void sendKeyPress(byte keyPress) {
    sendKeyPress(keyPress, 0);
  }

  //sendKeyPress: sends a key press only, with modifiers - no release
  //to release the key, send again with keyPress=0
  void sendKeyPress(byte keyPress, byte modifiers) {
    while (!usbInterruptIsReady()) {
      // Note: We wait until we can send keyPress
      //       so we know the previous keyPress was
      //       sent.
        usbPoll();
        _delay_ms(5);
    }

    memset(reportBuffer, 0, sizeof(reportBuffer));

    reportBuffer[0] = modifiers;
    reportBuffer[3] = keyPress;

    usbSetInterrupt(reportBuffer, sizeof(reportBuffer));
  }

  size_t write(uint8_t chr) {
    uint8_t data = pgm_read_byte_near(ascii_to_scan_code_table + (chr - 8));
    sendKeyStroke(data & 0b01111111, data >> 7 ? MOD_SHIFT_RIGHT : 0);
    return 1;
  }

  //private: TODO: Make friend?
  uchar    reportBuffer[8];    // buffer for HID reports [ 1 modifier byte + (len-1) key strokes]
  using Print::write;
};

DigiKeyboardDevice DigiKeyboard = DigiKeyboardDevice();

#ifdef __cplusplus
extern "C"{
#endif
  // USB_PUBLIC uchar usbFunctionSetup
    uchar usbFunctionSetup(uchar data[8]) {
    usbRequest_t    *rq = (usbRequest_t *)((void *)data);

    usbMsgPtr = DigiKeyboard.reportBuffer; //
    if ((rq->bmRequestType & USBRQ_TYPE_MASK) == USBRQ_TYPE_CLASS) {
      /* class request type */

      if (rq->bRequest == USBRQ_HID_GET_REPORT) {
                /* wValue: ReportType (highbyte), ReportID (lowbyte) */

                /* we only have one report type, so don't look at wValue */
        // TODO: Ensure it's okay not to return anything here?
                return 0;

      } else if (rq->bRequest == USBRQ_HID_GET_IDLE) {
                //usbMsgPtr = &idleRate;
                //return 1;
                return 0;

      } else if (rq->bRequest == USBRQ_HID_SET_IDLE) {
                idleRate = rq->wValue.bytes[1];

      }
    } else {
      /* no vendor specific requests implemented */
    }

    return 0;
  }
#ifdef __cplusplus
} // extern "C"
#endif

#endif // __DigiKeyboard_h__

Welcome to SE/Arduino! Please take the [tour] to learn how this site works, and read "[ask]". Then come back and [edit] your question to clarify. -- Do you have access to a USB analyzer/sniffer? If so, please tap the USB connection and watch the enumeration process and what follows. -- Did you search for information of the HP's requirements for keyboards, what did you find, and why does it not help you? -- Do you have another USB keyboard that works? If so, you might want to connect it to a Linux computer and look into the system logs for difference between that and your DigiKeyboard.

Thank you for your response. In asking what I tried, you answered my question of what I can try. Didn't know USB analyzer/sniffers existed. And the idea of checking it against a known good keyboard in linux is great. Thank you for your help!

Thanks for the flowers! However, these are just the next steps without guarantee of progress, but might help to finally find the solution. If you do, please come back and write an actual answer, marking it (later) as accepted.

"a custom version of the DigiKeyboard library" is likely part of the problem based on what I see.  But confirmation is in what I don't see. Where is the rest of the code?

source: Stack Exchange

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

sort: votes


text:
Importing content of text file as string into Arduino code
Is there any macro for importing the content of a file (for example html code) located in the sketch folder as a string for the Arduino IDE during compilation time?

For ESP32 (and ESP8266), you can partition part of the Flash memory to be used as the file system and creating a data/ folder in your project for storing files. Take a look at arduino-esp32littlefs-plugin (used for uploading the data to the partition) on how to install the plugin in Arduino IDE, and the LittleFS library or SPIFFS on how to use it to store and retrieve data.
I have a project on my github showing how the SPIFFS is used for storing webpages (html, JavaScript, CSS, icon, etc.) and serve it via an Async ESP32 Server. Following the link on the github for more detail explanation on the blog.

This is a very nice little project: modern and straightforward approach, the code is short and simple, very clear explanations in your blog… It could make a good “reference example” of sorts for people aiming to build a Web server for a hardware project.

Thank you @EdgarBonet for your compliments.

Try using the C++ Raw String Literal.
It's in the form of
const char *myLiteralText=R"abc123~~~(
   this is
   literal text
   which includes all spaces
   and newlines
)abc123~~~"

The abc123~~~ is a delimiter.
The test.h file must be modified by adding the first and last lines.
Actually, the last line can be in the test.ino file after the #include line, so only the first line has to be added to the test.h file.
Example at https://wokwi.com/projects/384484092370522113
test.ino
void setup() {

  Serial.begin(9600);

  const char *index_html=
    #include "test.h"
  ;

  Serial.print(index_html);

}

void loop() {}

test.h
R"html(

<!DOCTYPE html>
<html lang="en">
  <head>
      <meta charset="UTF-8">
      <title>VIPSDK MONITOR</title>
      <meta http-equiv="refresh" content="10">
  </head>
  <style type="text/css">
  </style>
</html>

)html"

In short, no. That I'm aware of the IDE, languages, and build system don't provide anything to do that automatically. It would be nice if C++ had something like Rust's include_str or include_bytes but so far as I know it still doesn't.
Your question is tagged with esp32. You may want to put strings on on your data partition if they're large.
There are other ways to do it, but the usual way to build arbitrary data into a C++ or C program is to run a utility that converts it into source code. Either into a string literal or an initialized array of some character type.
The xxd utility that usually comes with VIM is one such utility. It's normally used to generate hex dumps of files, but can be told to produce source code of an initialized array. Utilities like that are often run in a pre-build stage of a more conventional build process for C++. You could probably hack something into platform.txt that would do it. Or into something like a git hook. But the IDE doesn't have that sort of flexibility.
Here's a webpage that does the same sort of thing. You may have to manually null terminate the array if you want to do this.

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


text:
Arduino bluefruit nrf52 - check if softdevice is "busy"
I'm using a Bluefruit nRF52 with Arduino framework, and using Bluefruit library. It's connected to the Bluefruit connect app, but also acting as an SPI slave for another device (an stm32).
I'm having to bit-bang the SPI as the Arduino SPI library won't work as a slave (for nordic nrf52 devices), and using a GPIO from the nRF52 to tell the stm32 I'm ready to receive SPI (normally 5 to 10 bytes), after it detects SPI nCS assertion. To bitbang the SPI data, I'm then waiting on an interrupt on rising edge SPI CLK, at which point clock in the MOSI data.
It's mostly working except the odd message (1 in 5ish full transfers) gets missed. I've traced this to one SPI clk interrupt being missed during the transfer. (each transfer is 10 bytes).
As the nrf52 softdevice has higher priority than any user code, including interrupt handlers - I'm wondering if the irq is being missed because it happens during a period where the softdevice is in control. which is asynchronous.
So I'm wondering if I wait until soft device takes control, then wait till its done, then I signal that I'm ready to receive over SPI, that will give me the best chance to receive a full message.
Is there a way that I can poll some flag / variable / register to know that the softdevice has just been busy?

It has SPI Slave (SPIS) with EasyDMA so you could just use that instead. But I suppose you are afraid of events and tasks and that semaphore

Hi KIIV thanks for the reply.  i can see the SPIS in the nordic low level files but its not implemented in the arduino SPI library.  i tried to make my own version (SPI.h and SPI_nrf52832.cpp) to handle SPIS but couldnt get it to work.


text:
Is is possible to install a bootloader to an Arduino clone without a physical programmer?
I got an Arduino UNO clone, connected it to my PC via USB. I can't upload any sketches.
Correct board and port are selected in the IDE.
Windows recognizes it as a device, even though it has a CH340 (known issue with Chinese clones), so drivers don't seem to be the issue.
All physical connections and wiring on the board seem good.
So I am led to believe that the bootloader is the issue.
After a bit of digging around, I didn't find a way to install an Arduino bootloader that didn't require a programmer device or an extra original Arduino board in hand.
Here is the console output after trying to upload a sketch.
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\lhyse\AppData\Local\Arduino15\packages\arduino\tools\avrdude\6.3.0-arduino17/etc/avrdude.conf"

     Using Port                    : COM3
     Using Programmer              : arduino
     Overriding Baud Rate          : 115200
     avrdude: stk500_recv(): programmer is not responding
     avrdude: stk500_getsync() attempt 1 of 10: not in sync: resp=0xaa
     avrdude: stk500_recv(): programmer is not responding
     avrdude: stk500_getsync() attempt 2 of 10: not in sync: resp=0xaa
     avrdude: stk500_recv(): programmer is not responding
     avrdude: stk500_getsync() attempt 3 of 10: not in sync: resp=0xaa
     avrdude: stk500_recv(): programmer is not responding
     avrdude: stk500_getsync() attempt 4 of 10: not in sync: resp=0xaa
     avrdude: stk500_recv(): programmer is not responding
     avrdude: stk500_getsync() attempt 5 of 10: not in sync: resp=0xaa
     avrdude: stk500_recv(): programmer is not responding
     avrdude: stk500_getsync() attempt 6 of 10: not in sync: resp=0xaa
     avrdude: stk500_recv(): programmer is not responding
     avrdude: stk500_getsync() attempt 7 of 10: not in sync: resp=0xaa
     avrdude: stk500_recv(): programmer is not responding
     avrdude: stk500_getsync() attempt 8 of 10: not in sync: resp=0xaa
     avrdude: stk500_recv(): programmer is not responding
     avrdude: stk500_getsync() attempt 9 of 10: not in sync: resp=0xaa
     avrdude: stk500_recv(): programmer is not responding
     avrdude: stk500_getsync() attempt 10 of 10: not in sync: resp=0xaa

     avrdude done.  Thank you.

     Failed uploading: uploading error: exit status 1

For devices with an Atmega MCU and no pre-installed bootloader, the answer is NO - it is not possible to install a bootloader without a physical programmer.
If there is a working bootloader, but not the one you need, it might be possible under some circumstances.

Lets assume an Atmega328p has a current bootloader that is only 512 bytes large (4 pages) and resides at 0x3F00-0x3FF and BOOTSZ=11.
One might use the current bootloader to program the new bootloader (also 512 bytes) into the application area just below the current bootloader to address 0x3E00-0x3EFF. Now, if the current bootloader is capable of changing fuses BOOTSZ=10, the next time a reset occurs, at least I think so, the new bootloader at 0x3E00 will be startet. The bootloaders should not overlap each other for this to work.

on ATmega 328p only a bootloader can write into the flash so it is not possible to replace the bootloader from application, unless the bootloader supports it


text:
I just downloaded the Arduino IDE and it doesn't compile any code
FQBN: arduino:avr:uno
Using board 'uno' from platform in folder: C:\Users\Kareem\AppData\Local\Arduino15\packages\arduino\hardware\avr\1.8.6
Using core 'arduino' from platform in folder: C:\Users\Kareem\AppData\Local\Arduino15\packages\arduino\hardware\avr\1.8.6

Detecting libraries used...
C:\Users\Kareem\AppData\Local\Arduino15\packages\arduino\tools\avr-gcc\7.3.0-atmel3.6.1-arduino7/bin/avr-g++ -c -g -Os -w -std=gnu++11 -fpermissive -fno-exceptions -ffunction-sections -fdata-sections -fno-threadsafe-statics -Wno-error=narrowing -flto -w -x c++ -E -CC -mmcu=atmega328p -DF_CPU=16000000L -DARDUINO=10607 -DARDUINO_AVR_UNO -DARDUINO_ARCH_AVR -IC:\Users\Kareem\AppData\Local\Arduino15\packages\arduino\hardware\avr\1.8.6\cores\arduino -IC:\Users\Kareem\AppData\Local\Arduino15\packages\arduino\hardware\avr\1.8.6\variants\standard C:\Users\Kareem\AppData\Local\Temp\arduino\sketches\249E86D7CFF632627E003BB52C94264B\sketch\Blink.ino.cpp -o nul
Generating function prototypes...
C:\Users\Kareem\AppData\Local\Arduino15\packages\arduino\tools\avr-gcc\7.3.0-atmel3.6.1-arduino7/bin/avr-g++ -c -g -Os -w -std=gnu++11 -fpermissive -fno-exceptions -ffunction-sections -fdata-sections -fno-threadsafe-statics -Wno-error=narrowing -flto -w -x c++ -E -CC -mmcu=atmega328p -DF_CPU=16000000L -DARDUINO=10607 -DARDUINO_AVR_UNO -DARDUINO_ARCH_AVR -IC:\Users\Kareem\AppData\Local\Arduino15\packages\arduino\hardware\avr\1.8.6\cores\arduino -IC:\Users\Kareem\AppData\Local\Arduino15\packages\arduino\hardware\avr\1.8.6\variants\standard C:\Users\Kareem\AppData\Local\Temp\arduino\sketches\249E86D7CFF632627E003BB52C94264B\sketch\Blink.ino.cpp -o C:\Users\Kareem\AppData\Local\Temp\43183129\sketch_merged.cpp
C:\Users\Kareem\AppData\Local\Arduino15\packages\builtin\tools\ctags\5.8-arduino11/ctags -u --language-force=c++ -f - --c++-kinds=svpf --fields=KSTtzns --line-directives C:\Users\Kareem\AppData\Local\Temp\43183129\sketch_merged.cpp
Compiling sketch...
"C:\\Users\\Kareem\\AppData\\Local\\Arduino15\\packages\\arduino\\tools\\avr-gcc\\7.3.0-atmel3.6.1-arduino7/bin/avr-g++" -c -g -Os -w -std=gnu++11 -fpermissive -fno-exceptions -ffunction-sections -fdata-sections -fno-threadsafe-statics -Wno-error=narrowing -MMD -flto -mmcu=atmega328p -DF_CPU=16000000L -DARDUINO=10607 -DARDUINO_AVR_UNO -DARDUINO_ARCH_AVR "-IC:\\Users\\Kareem\\AppData\\Local\\Arduino15\\packages\\arduino\\hardware\\avr\\1.8.6\\cores\\arduino" "-IC:\\Users\\Kareem\\AppData\\Local\\Arduino15\\packages\\arduino\\hardware\\avr\\1.8.6\\variants\\standard" "C:\\Users\\Kareem\\AppData\\Local\\Temp\\arduino\\sketches\\249E86D7CFF632627E003BB52C94264B\\sketch\\Blink.ino.cpp" -o "C:\\Users\\Kareem\\AppData\\Local\\Temp\\arduino\\sketches\\249E86D7CFF632627E003BB52C94264B\\sketch\\Blink.ino.cpp.o"
Compiling libraries...
Compiling core...
Using precompiled core: C:\Users\Kareem\AppData\Local\Temp\arduino\cores\arduino_avr_uno_06fe87695d748aefc72866d7f296b9a5\core.a
Linking everything together...
"C:\\Users\\Kareem\\AppData\\Local\\Arduino15\\packages\\arduino\\tools\\avr-gcc\\7.3.0-atmel3.6.1-arduino7/bin/avr-gcc" -w -Os -g -flto -fuse-linker-plugin -Wl,--gc-sections -mmcu=atmega328p -o "C:\\Users\\Kareem\\AppData\\Local\\Temp\\arduino\\sketches\\249E86D7CFF632627E003BB52C94264B/Blink.ino.elf" "C:\\Users\\Kareem\\AppData\\Local\\Temp\\arduino\\sketches\\249E86D7CFF632627E003BB52C94264B\\sketch\\Blink.ino.cpp.o" "C:\\Users\\Kareem\\AppData\\Local\\Temp\\arduino\\sketches\\249E86D7CFF632627E003BB52C94264B/..\\..\\cores\\arduino_avr_uno_06fe87695d748aefc72866d7f296b9a5\\core.a" "-LC:\\Users\\Kareem\\AppData\\Local\\Temp\\arduino\\sketches\\249E86D7CFF632627E003BB52C94264B" -lm
c:/users/kareem/appdata/local/arduino15/packages/arduino/tools/avr-gcc/7.3.0-atmel3.6.1-arduino7/bin/../lib/gcc/avr/7.3.0/../../../../avr/lib/avr5/crtatmega328p.o:(.init9+0x0): undefined reference to `main'
collect2.exe: error: ld returned 1 exit status

exit status 1

Compilation error: exit status 1

Looks like precompiled core doesn't contain main or something...

delete C:\Users\Kareem\AppData\Local\Temp\arduino\cores\arduino_avr_uno_06fe87695d748aefc72866d7f296b9a5\core.a and try again

@hcheung .cpp.ino is created by the Arduino builder

I have same problem. I can find "main.cpp.o" in core.a. it's confused


text:
Is it "safe" to use "new" keyword to instantize several sensor objects?
I've read that it is bad practice to use dynamic memory allocations on a microcontroller and I have a pretty good grasp of why.
I am developing a custom PCB around an ATMega2560 and in my situation, I need to create 24 objects for one kind of sensor and 8 more for another.
With a small number of sensors, you might create objects like this:
Ezo_board PH = Ezo_board(99, "PH");       //create a PH circuit object, who's address is 99 and name is "PH"
Ezo_board EC = Ezo_board(100, "EC");      //create an EC circuit object who's address is 100 and name is "EC"

But since I have so many and I want to loop through them I created a pointer array
Ezo_board *EC[maxEC];
and in setup function I wrote:
for (uint8_t i = 0; i < maxEC; i++)
 {
  EC[i] = new Ezo_board(i+11) //passing the I2C address which start at 11 and increment

I never delete the Ezo_board objects in the code. Is this a safe way to use dynamic memory allocation or is there a better way to do this while still maintaining ability to loop through the sensors in subsequent code?

Why do you think you need dynamic allocation? It can be Ezo_board boards[] = {{99,"PH"}, {100,"EC"}, };, or if it has ambiguous constructors you'll need  = {Ezo_board(99, "PH"), Ezo_board(100, "EC"), }

My concern was with hard coding all the sensors in when I may wish to adjust the number of sensors used on a given board. By defining a number of sensors (maxEC), I just need to change a constant.

Well, arduino supports c++11 standard for a while, you can use range based for loop like:  for (auto & sensor : sensors)  { ...  and you don't have to know the size

I hadn't heard of range based loops before, I'll look that up!

The danger in using dynamic memory on embedded devices lies in repeated allocation & de-allocation of chunks of memory. The memory allocator splits off a piece of memory for each allocation. When one is returned the de-allocator joins it - or should join it - with an adjacent free chunk, if there is one, to create a larger free chunk instead of two adjacent smaller ones. But that is a big 'if': 1) does the particular memory-manager even try to do that? and 2) in too many instances, it won't even be possible.
The net result is that the memory pool becomes a bunch of small fragments that aren't join-able and aren't large enough to satisfy further requests.
In your scenario, dynamic allocation at the start of the run with no further returns and re-alloacation, there is very little difference between it and static allocation, other than the static allocation would have be done at load-time, just before the run begins.
Either way is fine in that case. If anyone else might ever look over your code, or if someday in the future you might come back to it and wonder whether this application might have created a fragmentation problem, then it's worth leaving a comment to make your intentions clear.
I should add here that when I need dynamic allocation in an embedded system, I write my own memory allocator that never splits free memory. Instead, it simply hands out one buffer from a statically allocated array of fixed size buffers for any request up to that size (and returns a failure code otherwise). Memory is never split or joined, so it never gets fragmented. As long as the demand for buffers is predictable and you allocate enough of them to meet the maximum demand, your system won't fail for running out of memory.

Yes, it is (in common sense) bad practise and you know why and you probabelly also know, why it is not problem in your case.
It is perfectly safe way and I do not see, why you should not do it this way.
I do similar things regularry and I have no problem with it.
I want my code working right and the readibility and maintainability are the more important steps in this way. So I structure my code in such way, that I can understand it easily even after couple of years.
There are many rules, how to make code better and there is some reason after each one. But some goes against others.
I have Arduino for fun and I use the rules as recomendations, but I am the Master of my code. So I sometime take other ways.
If it helps me to see the code better organized, I have not problem to do things my own way.
(In large corporation, where you must share code with many others, the formal rules are more important, as they helps all to be at the same platform. There you are payed to stick to rules.
In home developement I share code mainly with myself and I am not paid. So I have to care mainly only about future me)


text:
OLED and Wifi not working together on ESP8266 Heltec NodeMCU
I have this ESP8266 Heltec NodeMCU board with OLED. The pins are described here.
I have the following problem. The both OLED (with u8g2) and Wifi work fine individually. There is a problem getting them working together.
In particular, the following code works (and shows Hello World, blanks the screen and then repeats):
#include <U8g2lib.h>
U8G2_SSD1306_128X32_UNIVISION_F_HW_I2C u8g2(U8G2_R0, U8X8_PIN_NONE);

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

void loop() {
  u8g2.setFont(u8g2_font_ncenB14_tr);
  u8g2.firstPage();
  do {
    u8g2.setCursor(0, 20);
    u8g2.print(F("Hello World!"));
  } while ( u8g2.nextPage() );
  delay(2000);
  u8g2.clear();
  delay(2000);
}

Adding the Wifi to the code (the only difference to the code above are the 2 lines in the setup).
#include <ESP8266WiFi.h>
#include <U8g2lib.h>
U8G2_SSD1306_128X32_UNIVISION_F_HW_I2C u8g2(U8G2_R0, U8X8_PIN_NONE);

void setup() {
  u8g2.begin();

  WiFi.begin ( "xxx", "yyy" );
  while ( WiFi.status() != WL_CONNECTED  ) { delay(500); }
}

void loop() {
  u8g2.setFont(u8g2_font_ncenB14_tr);
  u8g2.firstPage();
  do {
    u8g2.setCursor(0, 20);
    u8g2.print(F("Hello World!"));
  } while ( u8g2.nextPage() );
  delay(2000);
  u8g2.clear();
  delay(2000);
}

In this case, "Hello World" appears 3 times and then the screen remains blank.
Edit:
I noticed something which, I believe, is an important piece of information when I turned the debugging of the WiFi on.
The display stops working after the output pm open,type:2 0 of the debugger. I believe that pm refers to powermanagement. Could it be that the system goes sleeping? How to prevent this from happening?

Does the WiFi actually connect, or are things stuck in the while loop in setup()?

It does connect. I just produced a minimal example.

@ocrdu: Interestingly, "Hello world" appears 3 times (deterministically) and then the screen remains blank.

replace all of the OLED code with a blinking LED ... maybe the problem has nothing to do with the OLED

Without the OLED, the WiFi works. So either OLED or WiFi work individually. Together, only the WiFi works. The OLED stops working after some time.

I managed to solve the issue and figure out what the problem is. I put here an answer for reference, if this question appears again. It turns out that the reset of the OLED is important. It is easy to see, if one uses the Adafruit_SSD1306 library. The code
  #define SCREEN_WIDTH 128
  #define SCREEN_HEIGHT 32
  #define OLED_RESET 0
  Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);

produces exactly the issues described in the text. Changing it into
  #define SCREEN_WIDTH 128
  #define SCREEN_HEIGHT 32
  #define OLED_RESET 16
  Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);

solves the issue. Similarly, replacing U8X8_PIN_NONE with 16 in the code above, runs as expected. It looks like the example provided with the board is incorrect.


text:
Adding a custom platform to PlatformIO
How can I add the STM32duino core as a custom platform to PlatformIO?

See https://docs.platformio.org/en/latest/platforms/ststm32.html

Creating custom board support for PlatformIO
PlatformIO provides a very comprehensive documentation on how to use PlatformIO for programming STM32 with various platforms. You can find "Custom Platform & Boards" on the side menu, which will lead you to this section of the document, which again is well documented.
It basically involves creating a JSON file that describes your custom platform or custom board. The easier way is to copy one of the family MCUs JSON configuration file that's already supported by the PlatformIO or STM32duino framework, and make modifications from there. For example, if your custom board is STM32G070xx, which is not supported by PlatformIO yet, you can find the board description JSON from platform-stm32 github repository for Nucleo_G070RB board and use it as a template to create your own custom board JSON structure.
Creating custom board support for Arduino IDE
The official STM32duino wiki provides a description on how to create a custom board variant on Arduino IDE for the framework. I also have an example of a custom variant for supporting my two custom boards in my github that you could take a look at in case you are interested to create custom board support under Arduino IDE.

the question is not about custom board

@juraj, One of the links that I provided including the information for creating custom platform manifest file under PlatformIO. OP mentioned STMduino which means a platform and a specific framework (arduino) has been defined, so I assumed what he means for "custom platform" actually means for "custom board". This is also why I at the beginning only provide a broader link instead of a specific link.  I will let the OP to decide what he is looking for.  If this is not what he is looking for, I'm sure OP will speak out.


text:
Which sketch was this?
With ESP32 being so plentiful here (3 more for Christmas) I am at a loss to determine which sketch I used for a particular unit. Has anyone devised a record keeping scheme or even a serial monitor feedback with the sketch details available when plugged back in to the PC?

What information do you want to see there exactly? You could just do a Serial print with some custom message (defined by you) inside setup(). Is that what you want?

I set up a precompile trigger that will run a shell script that grabs the current git hash and puts it in a file as a #define.  From my sketch I print that.  Then I know which file and which version is loaded.

Early in setup() I print one line to the terminal with the .ino file's name, revision, and date. I keep all projects under source-code control which maintains that line without any effort from me, as long as I've included the small snippet of data and  and the Serial.println() call to print it.
Update:

Can you show some code how you include the automatic revision identification into the Arduino Build Chain?

Here's an example. Note that the build-chain isn't modified; everything happens in the source code, RCS, in my case. You'll probably have to tweak the keyword that gets the revision data, ($Id$ in RCS) for whatever source control you use. If you aren't using source control, you could print the compile-time macros suggested by @DataFiddler.
/*
 * Macro to tell ::println() & family to expact a pointer to Flash memory
 * #define this in your library's local.h file, or where ever you'd
 * put your personal, site-unique, or non-public macros like your
 * WiFi password:
 *
 * #define FLSTR_HLP(str) (const __FlashStringHelper *)str
 * (Look up __FlashStringHelper for more information)
 *
 */
// ----------------------------------
// Your .ino file would start here:

#include <local.h>                        // gets the above #define

// Define one of these in each .ino file:
// const char IdString[] PROGMEM = $Id$
// RCS expands or updates it to something like this,
//  every time you check out any version:
//  (Other source control systems will have similar facilities)
const char IdString[] PROGMEM = "$Id: HowTo_IdString.ino,v 1.1 2023-12-26 18:16:06-05 jrobert Exp $";   // def an IdString in Flash

void setup() {
   Serial.begin(115200);
   Serial.print("");
   Serial.println(FLSTR_HLP(IdString));   // prints the IdString from Flash

   // .. more setup ..
}

void loop() {
   Serial.print(F("Run time: "));
   Serial.println(millis());
   delay(5000);
}

Interesting. Can you show some code how you include the automatic revision identification into the Arduino Build Chain?

Serial.println(__DATE__);   Serial.println(__TIME__);  shows compilation date and time. Should be close to source file save time.

If you want just a simple way of identification, use some of the compiler's predefined macros* as automagic source of information:
void setup() {
  while (!Serial);
  Serial.begin(115200);
  Serial.print("(");
  Serial.print(__VERSION__);
  Serial.print(") ");
  Serial.print(__FILE__);
  Serial.print(": ");
  Serial.print(__DATE__);
  Serial.print(", ");
  Serial.println(__TIME__);
}

void loop() {
}

The output of the sketch is:
(7.3.0) /home/XXXXXXXX/name_of_sketch.ino: Dec 27 2023, 23:03:58

*) In my case (Arduino IDE version 1.8.19) the version of G++ is 7.3.0.


text:
Joystick library not reading potentiometer
I am using Joystick Library to make a HOTAS system for flight simulators. When I load the test program I can get all the simulated controller inputs to register in windows. I can also get the value from my slide potentiometer to read in the serial monitor. But it will not change the value of the input function i pass it to. my guess is its the wrong kind of integer but I don't know very much about int types. Joystick.setThrottle has an int32_t as a parameter. Windows reads the value of throttle at 49% when its connected.
What I have tried:
changing the range (the default is 0 to 1023 I want it to be 0 to 255)
changing the type of throttle_ to int, unsigned int, and int_32_t
changing initAutoSendState
using the pin number instead of the macro throttle
passing throttle_ directly into Joystick.setThrottle without the updateThrottle function
I have some programming experience from my high school class so I just tried different approaches but I am new to Arduino.
#include "Joystick.h"
//define input pins
#define throttle A0
//include hid, type, button count, hat count, x axis, y axis, z axis, Rx axis, Ry axis, Rz axis, rudder, Throttle, Accelerator,  Brake, Steering
Joystick_ Joystick(JOYSTICK_DEFAULT_REPORT_ID,JOYSTICK_TYPE_JOYSTICK, 0, 0, false, false, false, false, false, false, false, true, false, false, false);
const bool initAutoSendState = true;

int32_t throttle_ = 0;
void updateThrottle (int32_t value)
{
Joystick.setThrottle(value);
}
void setup() {
  // put your setup code here, to run once:

Serial.begin(9600);
pinMode(throttle, INPUT_PULLUP);
Joystick.setThrottleRange(0, 255);

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

  throttle_ = analogRead(throttle);
  throttle_ = map(throttle_, 0, 1023, 0,  255);
updateThrottle(throttle_);
Serial.print(throttle_);
Serial.print("\n");

}

Looking through the examples turns out I needed to add Joystick.begin(); to the setup


text:
Photoresistor Matrix has the same values
I'm a second-year System Engineer student who needs to make a project for class.
I have a 4x4 matrix of photoresistors that goes to an analog digital multiplexer connected to an Arduino Uno. This setup is put in a box with a lid. The lid has a hole in the middle of the matrix. I want to calculate the angle of a light source depending on the photoresistors' readings. Basically, I want to recreate a Sattelite Sun Sensor.
I have the following problem: all the photoresistors from a row have the same reading, even if I try to isolate one of them and shine a light on it. In the column, everything works well.
This is my circuit on a 2 layers PCB:
(C0-C15, SIG, S0-S3, EN are the pins of the CD74HC4067 Multiplexer)

Also, this is my code:
//Mux control pins
int s0 = 11;
int s1 = 10;
int s2 = 9;
int s3 = 8;

//Mux in "SIG" pin
int SIG_pin = 0;
float values[4][4] = {0.0};

void setup(){
  pinMode(s0, OUTPUT);
  pinMode(s1, OUTPUT);
  pinMode(s2, OUTPUT);
  pinMode(s3, OUTPUT);

  digitalWrite(s0, LOW);
  digitalWrite(s1, LOW);
  digitalWrite(s2, LOW);
  digitalWrite(s3, LOW);

  Serial.begin(9600);
}

void loop(){

  //Loop through and read all 16 values
  for(int i = 0; i < 4; ++i)
      for(int j = 0; j < 4; ++j){
        values[i][j] = readMux(i);
        delay(500);
      }

  Serial.println("-----Matrix-----");
  for(int i = 0; i < 4; ++i){
      for(int j = 0; j < 4; ++j){
        Serial.print(values[i][j]);
        Serial.print(" ");
        delay(100);
    }
    Serial.println();
  }
  Serial.println();
  Serial.print(calculateAngle());
  Serial.println();
  delay(1000);
}

float calculateAngle(){
  const int dx[] = {-2, -1, 1, 2, -2, -1, 1, 2, -2, -1, 1, 2, -2, -1, 1, 2};
  const int dy[] = {-2, -2, -2, -2, -1, -1, -1, -1, 1, 1, 1, 1, 2, 2, 2, 2};
  float x = 0, y = 0;

  for(int i = 0; i < 16; ++i){
    x += dx[15 - i] * values[i / 4][i % 4];
    y += dy[15 - i] * values[i / 4][i % 4];
  }
  Serial.print(x);
  Serial.print(" ");
  Serial.print(y);
  Serial.print(" ");
  return atan2(y, x) * 180 / 3.14;
}

float readMux(int channel){
  int controlPin[] = {s0, s1, s2, s3};

  int muxChannel[16][4]={
    {0,0,0,0}, //channel 0
    {1,0,0,0}, //channel 1
    {0,1,0,0}, //channel 2
    {1,1,0,0}, //channel 3
    {0,0,1,0}, //channel 4
    {1,0,1,0}, //channel 5
    {0,1,1,0}, //channel 6
    {1,1,1,0}, //channel 7
    {0,0,0,1}, //channel 8
    {1,0,0,1}, //channel 9
    {0,1,0,1}, //channel 10
    {1,1,0,1}, //channel 11
    {0,0,1,1}, //channel 12
    {1,0,1,1}, //channel 13
    {0,1,1,1}, //channel 14
    {1,1,1,1}  //channel 15
  };
  DDRB = 0;
  //loop through the 4 sig
  for(int i = 0; i < 4; i ++)
    DDRB |= (1 << i) & muxChannel[channel][i]; //faster than digitalWrite(controlPin[i], muxChannel[channel][i]);
  delay(100);
  //read the value at the SIG pin
  int val = analogRead(SIG_pin);
  //convert the value in voltage
  float voltage = (val * 5.0) / 1024.0;
  //return the voltage
  return voltage;
}

Example of a bogus reading:
-----Matrix-----
0.13 0.14 0.13 0.12
3.14 3.17 3.12 2.96
0.12 0.12 0.11 0.12
2.77 2.81 2.83 2.77

What am I doing wrong? Did I make a mistake in my code or connecting everything together? Thank you for any help!

This is probably, because you don't actually set the MUX pins. The DDRx registers set the Data Direction of the port pins. A 1 in there means, that the pin corresponding to that bit is set as output. A zero means, it is set as input. The output state of a pin is controlled by the PORTx registers. If the DDRx bits are set to input and the PORTx bits are set to 1, then the internal pullup resistor is activated.
In setup you set all the MUX pins to OUTPUT and LOW, so DDRB with 1s and PORTB with zeros. Then in readMux() you are just setting bits in DDRB via the (overcomplicated) line:
DDRB |= (1 << i) & muxChannel[channel][i];

So you are switching the pins between OUTPUT+LOW and INPUT+NO_PULLUP. Instead you should write to the PORTB register, which controls the output state of the port B pins.
Also writing the mux channel can be done way easier. When you look at your array in readMux() you might notice, that the channel patters are just a binary number. So you have the following channel number to pattern relationship:
channel  0 --> binary 0000 --> decimal 0
channel  1 --> binary 0001 --> decimal 1
channel  2 --> binary 0010 --> decimal 2
channel  3 --> binary 0011 --> decimal 3
...
channel 10 --> binary 1010 --> decimal 10
...

So instead of using the above overcomplicated line, you can just write the channel number to the 4 target bits of PORTB:
PORTB |= channel & 0b00001111;

You don't even need to for loop for that. The & 0b00001111 part is only for cutting the channel number to only ever use the first 4 bits of the register (keeping it down between 0 and 15).

So this solved one of the problems. The main one was that I was reading just 4 channels 4 times instead of all different 16, thus why the values were similar. Thank you so much for helping me and for the code optimization!


text:
ESP32-CAM camera: SD help
I'm struggling with making a simple sketch to take a photo with an ESP32-CAM and save to an SD card.
I have found a bunch of examples that that do what I want, but basically they just take a photo and go to sleep, so every time you reset the unit it runs some code to take a photo, then goes into deep sleep.
The thing is the photos suck, they are green and have no exposure control. I think that it is a known issue that the first photo is always green and the auto gain has not figured out the exposure yet. So because every photo is the first photo after waking up, they all suck.
I tried to move the setup stuff into the loop, and remove the sleep part, but it just straight up doesn't work, and I don't understand enough about coding to even get ChatGPT to help.
I will put the working code below, and then the part I changed. Any help would be great. I thought it would be so simple, I just want to take a photo when I push a button.
/*
ESP32 CAM Camera with MicroSD storage
  esp32cam-microsd.ino
  Take picture when button pressed
  Store image on MicroSD card

  DroneBot Workshop 2022
  https://dronebotworkshop.com
*/
// Include Required Libraries

// Camera libraries
#include "esp_camera.h"
#include "soc/soc.h"
#include "soc/rtc_cntl_reg.h"
#include "driver/rtc_io.h"

// MicroSD Libraries
#include "FS.h"
#include "SD_MMC.h"

// EEPROM Library
#include "EEPROM.h"

// Use 1 byte of EEPROM space
#define EEPROM_SIZE 1

// Counter for picture number
unsigned int pictureCount = 0;

// Pin definitions for CAMERA_MODEL_AI_THINKER
#define PWDN_GPIO_NUM     32
#define RESET_GPIO_NUM    -1
#define XCLK_GPIO_NUM      0
#define SIOD_GPIO_NUM     26
#define SIOC_GPIO_NUM     27
#define Y9_GPIO_NUM       35
#define Y8_GPIO_NUM       34
#define Y7_GPIO_NUM       39
#define Y6_GPIO_NUM       36
#define Y5_GPIO_NUM       21
#define Y4_GPIO_NUM       19
#define Y3_GPIO_NUM       18
#define Y2_GPIO_NUM        5
#define VSYNC_GPIO_NUM    25
#define HREF_GPIO_NUM     23
#define PCLK_GPIO_NUM     22

void configESPCamera() {
  // Configure Camera parameters

  // Object to store the camera configuration parameters
  camera_config_t config;

  config.ledc_channel = LEDC_CHANNEL_0;
  config.ledc_timer = LEDC_TIMER_0;
  config.pin_d0 = Y2_GPIO_NUM;
  config.pin_d1 = Y3_GPIO_NUM;
  config.pin_d2 = Y4_GPIO_NUM;
  config.pin_d3 = Y5_GPIO_NUM;
  config.pin_d4 = Y6_GPIO_NUM;
  config.pin_d5 = Y7_GPIO_NUM;
  config.pin_d6 = Y8_GPIO_NUM;
  config.pin_d7 = Y9_GPIO_NUM;
  config.pin_xclk = XCLK_GPIO_NUM;
  config.pin_pclk = PCLK_GPIO_NUM;
  config.pin_vsync = VSYNC_GPIO_NUM;
  config.pin_href = HREF_GPIO_NUM;
  config.pin_sscb_sda = SIOD_GPIO_NUM;
  config.pin_sscb_scl = SIOC_GPIO_NUM;
  config.pin_pwdn = PWDN_GPIO_NUM;
  config.pin_reset = RESET_GPIO_NUM;
  config.xclk_freq_hz = 20000000;
  config.pixel_format = PIXFORMAT_JPEG; // Choices are YUV422, GRAYSCALE, RGB565, JPEG

  // Select lower framesize if the camera doesn't support PSRAM
  if (psramFound()) {
    config.frame_size = FRAMESIZE_UXGA; // FRAMESIZE_ + QVGA|CIF|VGA|SVGA|XGA|SXGA|UXGA
    config.jpeg_quality = 10; //10-63 lower number means higher quality
    config.fb_count = 2;
  } else {
    config.frame_size = FRAMESIZE_UXGA;
    config.jpeg_quality = 12;
    config.fb_count = 1;
  }

  // Initialize the Camera
  esp_err_t err = esp_camera_init(&config);
  if (err != ESP_OK) {
    Serial.printf("Camera init failed with error 0x%x", err);
    return;
  }

  // Camera quality adjustments
  sensor_t * s = esp_camera_sensor_get();

  // BRIGHTNESS (-2 to 2)
  s->set_brightness(s, 0);
  // CONTRAST (-2 to 2)
  s->set_contrast(s, 1);
  // SATURATION (-2 to 2)
  s->set_saturation(s, 0);
  // SPECIAL EFFECTS (0 - No Effect, 1 - Negative, 2 - Grayscale, 3 - Red Tint, 4 - Green Tint, 5 - Blue Tint, 6 - Sepia)
  s->set_special_effect(s, 2);
  // WHITE BALANCE (0 = Disable , 1 = Enable)
  s->set_whitebal(s, 1);
  // AWB GAIN (0 = Disable , 1 = Enable)
  s->set_awb_gain(s, 1);
  // WB MODES (0 - Auto, 1 - Sunny, 2 - Cloudy, 3 - Office, 4 - Home)
  s->set_wb_mode(s, 0);
  // EXPOSURE CONTROLS (0 = Disable , 1 = Enable)
  s->set_exposure_ctrl(s, 1);
  // AEC2 (0 = Disable , 1 = Enable)
  s->set_aec2(s, 0);
  // AE LEVELS (-2 to 2)
  s->set_ae_level(s, 0);
  // AEC VALUES (0 to 1200)
  s->set_aec_value(s, 300);
  // GAIN CONTROLS (0 = Disable , 1 = Enable)
  s->set_gain_ctrl(s, 1);
  // AGC GAIN (0 to 30)
  s->set_agc_gain(s, 0);
  // GAIN CEILING (0 to 6)
  s->set_gainceiling(s, (gainceiling_t)0);
  // BPC (0 = Disable , 1 = Enable)
  s->set_bpc(s, 0);
  // WPC (0 = Disable , 1 = Enable)
  s->set_wpc(s, 1);
  // RAW GMA (0 = Disable , 1 = Enable)
  s->set_raw_gma(s, 1);
  // LENC (0 = Disable , 1 = Enable)
  s->set_lenc(s, 1);
  // HORIZ MIRROR (0 = Disable , 1 = Enable)
  s->set_hmirror(s, 0);
  // VERT FLIP (0 = Disable , 1 = Enable)
  s->set_vflip(s, 0);
  // DCW (0 = Disable , 1 = Enable)
  s->set_dcw(s, 1);
  // COLOR BAR PATTERN (0 = Disable , 1 = Enable)
  s->set_colorbar(s, 0);
}

void initMicroSDCard() {
  // Start the MicroSD card
  Serial.println("Mounting MicroSD Card");
  if (!SD_MMC.begin()) {
    Serial.println("MicroSD Card Mount Failed");
    return;
  }
  uint8_t cardType = SD_MMC.cardType();
  if (cardType == CARD_NONE) {
    Serial.println("No MicroSD Card found");
    return;
  }
}

void takeNewPhoto(String path) {
  // Take Picture with Camera
  // Setup frame buffer
  camera_fb_t  * fb = esp_camera_fb_get();

  if (!fb) {
    Serial.println("Camera capture failed");
    return;
  }

  // Save picture to microSD card
  fs::FS &fs = SD_MMC;
  File file = fs.open(path.c_str(), FILE_WRITE);
  if (!file) {
    Serial.println("Failed to open file in write mode");
  }
  else {
    file.write(fb->buf, fb->len); // payload (image), payload length
    Serial.printf("Saved file to path: %s\n", path.c_str());
  }
  // Close the file
  file.close();

  // Return the frame buffer back to the driver for reuse
  esp_camera_fb_return(fb);
}

void setup() {
  // Disable brownout detector
  WRITE_PERI_REG(RTC_CNTL_BROWN_OUT_REG, 0);

  // Start Serial Monitor
  Serial.begin(115200);

  // Initialize the camera
  Serial.print("Initializing the camera module...");
  configESPCamera();
  Serial.println("Camera OK!");

  // Initialize the MicroSD
  Serial.print("Initializing the MicroSD card module... ");
  initMicroSDCard();

  // initialize EEPROM with predefined size
  EEPROM.begin(EEPROM_SIZE);
  pictureCount = EEPROM.read(0) + 1;

  // Path where new picture will be saved in SD Card
  String path = "/image" + String(pictureCount) + ".jpg";
  Serial.printf("Picture file name: %s\n", path.c_str());

  // Take and Save Photo
  takeNewPhoto(path);

  // Update EEPROM picture number counter
  EEPROM.write(0, pictureCount);
  EEPROM.commit();

  // Bind Wakeup to GPIO13 going LOW
  esp_sleep_enable_ext0_wakeup(GPIO_NUM_13, 0);

  Serial.println("Entering sleep mode");
  delay(1000);

  // Enter deep sleep mode
  esp_deep_sleep_start();
}

void loop() {
}

I changed the set up and loop:
void setup() {
  // Disable brownout detector
  WRITE_PERI_REG(RTC_CNTL_BROWN_OUT_REG, 0);

  // Start Serial Monitor
  Serial.begin(115200);

  // Initialize the camera
  Serial.print("Initializing the camera module...");
  configESPCamera();
  Serial.println("Camera OK!");

  // Initialize the MicroSD
  Serial.print("Initializing the MicroSD card module... ");
  initMicroSDCard();

  // initialize EEPROM with predefined size
  EEPROM.begin(EEPROM_SIZE);
  pictureCount = EEPROM.read(0) + 1;
}

void loop() {
  // Path where the new picture will be saved on the SD Card
  String path = "/image" + String(pictureCount) + ".jpg";
  Serial.printf("Picture file name: %s\n", path.c_str());

  // Check if GPIO13 is low
  if (digitalRead(GPIO_NUM_13) == LOW) {
    // Take and Save Photo
    takeNewPhoto(path);

    // Update EEPROM picture number counter
    EEPROM.write(0, pictureCount);
    EEPROM.commit();

  }
}

Read this web page, in the section take photo to SD card
fb = esp_camera_fb_get();
dealy(1000)////

This is key to avoid an issue with the image being very dark and green. If needed adjust total delay time.
fb = esp_camera_fb_get();

Hope this helps,
I would suggest take some image buffers first wake the camera up then write the data later to SD card.

thanks, this helped with the green some of the time, but is way too delayed to be piratical, and does not address the exposure problem.  I really need to keep the ESP on and just trigger the photo capture code with a button.


text:
UCSR0B equivalent for ESP2866
I'm trying to convert an Arduino Uno program for use with the ESP2866. I've converted most of the program successfully, but there are a few lines I can't seem to figure out. For example,
  UCSR0B = 0b10011101;
  UCSR0B = 0b10011100;

These lines result in the following error:
Compilation error: 'UCSR0B' was not declared in this scope

My understanding is that these lines modify parameters within one of the Uno's serial registers. Is it possible to do the equivalent action on the ESP? I have tried researching this but have found very little info online. I am using Arduino IDE v2.2.1. Thank you!

When porting software from one target to another, especially if it accesses hardware directly, always needs reading and understanding the documentation of both targets. Before you post a question here, you are supposed to do this homework, which you apparently did not.

UCSR0B is the UART Control and Status Register on an ATMEGA328, the processor used on many Arduino models. This is extract from the ATMEGA328 datasheet shows what the bits do:

Setting it to 0b10011101 enables RXCIE, RXEN,TXEN, UCSZ2 and TXB, and setting to the 0b10011100 sets all of the bits except TXB. Setting UCSZ2 enables 9-bit mode, and setting or clearing TXB sets or clears the ninth bit for transmitted data.
Taking a quick look at the ESP8266 UART config, the UART supports a maximum of 8 bits, so if your app definitely requires 9 bits, you won't be able to do it on an ESP8266.
typedef enum {
    UART_DATA_5_BITS = 0x0,    /*!< word length: 5bits*/
    UART_DATA_6_BITS = 0x1,    /*!< word length: 6bits*/
    UART_DATA_7_BITS = 0x2,    /*!< word length: 7bits*/
    UART_DATA_8_BITS = 0x3,    /*!< word length: 8bits*/
} uart_word_length_t;


text:
How to check if the MQTT connection is still active?
I am wondering if there is a way to check and see if the MQTT connection is still active.
The reason for this is that I am having trouble with the connection dropping after a short while and not seeming to reconnect.
/*
  ArduinoMqttClient - WiFi Simple Sender

  This example connects to a MQTT broker and publishes a message to
  a topic once a second.

  The circuit:
  - Arduino MKR 1000, MKR 1010 or Uno WiFi Rev2 board

  This example code is in the public domain.
*/

#include <ArduinoMqttClient.h>
#include <MKRGSM.h>

#include "arduino_secrets.h"
// Please enter your sensitive data in the Secret tab or arduino_secrets.h
// PIN Number
const char PINNUMBER[]     = SECRET_PINNUMBER;
// APN data
const char GPRS_APN[]      = SECRET_GPRS_APN;
const char GPRS_LOGIN[]    = SECRET_GPRS_LOGIN;
const char GPRS_PASSWORD[] = SECRET_GPRS_PASSWORD;

GSMClient client;
GPRS gprs;
GSM gsmAccess;
MqttClient mqttClient(client);

const char broker[] = "*****";
int        port     = 1883;
const char topic[]  = "Tempdata";

const long interval = 500000;
unsigned long previousMillis = 0;

float SERIESRESISTOR = 9.87;
float TEMPERATURENOMINAL = 25.0;
float BCOEFFICIENT = 3540.0;
float thermistor = 0.0;
float THERMISTORNOMINAL = 10;

int count = 0;

void setup() {
  // Initialize serial and wait for port to open:
  Serial.begin(9600);

  Serial.println("Starting Arduino web client.");
  // connection state
  bool connected = false;

  // After starting the modem with GSM.begin()
  // attach the shield to the GPRS network with the APN, login and password
  while (!connected) {
    if ((gsmAccess.begin(PINNUMBER) == GSM_READY) &&
        (gprs.attachGPRS(GPRS_APN, GPRS_LOGIN, GPRS_PASSWORD) == GPRS_READY)) {
      connected = true;
    } else {
      Serial.println("Not connected");
      delay(1000);
    }
  }

  Serial.println("You're connected to the network");
  Serial.println();

  // You can provide a unique client ID, if not set the library uses Arduino-millis()
  // Each client must have a unique client ID
  mqttClient.setId("pump-house-gsm");

  // You can provide a username and password for authentication
  //mqttClient.setUsernamePassword("****", "****");

  Serial.print("Attempting to connect to the MQTT broker: ");
  Serial.println(broker);

  if (!mqttClient.connect(broker, port)) {
    Serial.print("MQTT connection failed! Error code = ");
    Serial.println(mqttClient.connectError());

    while (1);
  }

  Serial.println("You're connected to the MQTT broker!");
  Serial.println();

  // set analog resulotion to 12
  analogReadResolution(12);
}

void loop() {
  // call poll() regularly to allow the library to send MQTT keep alives which
  // avoids being disconnected by the broker
  mqttClient.poll();

  // to avoid having delays in loop, we'll use the strategy from BlinkWithoutDelay
  // see: File -> Examples -> 02.Digital -> BlinkWithoutDelay for more info
  unsigned long currentMillis = millis();

  if (currentMillis - previousMillis >= interval) {
    /*Read analog outputof NTC module,
     i.e the voltage across the thermistor */
    float average = ((float)analogRead(A0) / 4095.0) * 3.3;

    average = (average * SERIESRESISTOR) / (3.3 - average);

    float steinhart;
    steinhart = average / THERMISTORNOMINAL;     // (R/Ro)
    steinhart = log(steinhart);                  // ln(R/Ro)
    steinhart /= BCOEFFICIENT;                   // 1/B * ln(R/Ro)
    steinhart += 1.0 / (TEMPERATURENOMINAL + 273.15); // + (1/To)
    steinhart = 1.0 / steinhart;                 // Invert
    steinhart -= 273.15;                         // convert absolute temp to C

    // save the last time a message was sent
    previousMillis = currentMillis;

    // Keep track of times a message was sent
    // this is to reconnect every hour.
    count = count + 1;

    // send message, the Print interface can be used to set the message contents
    mqttClient.beginMessage(topic);
    mqttClient.print("The temperature is ");
    mqttClient.print(steinhart);
    mqttClient.endMessage();
  }
}

Maybe endMessage, beginMessage, or poll has a return that says it has failed to send a message?
I've looked at endMessage and beginMessage and it does not seem like it to me, but poll is much more complicated and I can't really tell.

I found the solution with the connected function included in the ArduinoMqttClient (found it browsing the library code).
Here is a code snippet showing what I added:
...
...
if (currentMillis - previousMillis >= interval) {
  if (!mqttClient.connected()) {
    if (mqttClient.connect(broker, port)) {
        Serial.println("reconnected");
    }
  }

  /*Read analog outputof NTC module,
  i.e the voltage across the thermistor */
  float average = ((float)analogRead(A0) / 4095.0) * 3.3;
...
...

It is working so far!


text:
inputs randomly turn on and off
I'm building the dactyl manuform, and I'm writing all of the code myself, but I've ran into a problem here's my code:
// the setup routine runs once when you press reset:
void setup() {
  Serial.begin(9600);

  for (int i=0;i<20;i++){
    pinMode(i, INPUT);
  }
}

// the loop routine runs over and over again forever:
void loop() {
  for (int i=0;i<20;i++){
    Serial.print(digitalRead(i));
  }
  Serial.print("\n");

  //delay(100); //uncomment if you want to
}

The problem is even when the inputs are not connected to 5V, the serial monitor sometimes gives a 1, and sometimes a 0. At first I was only using analog inputs, so I was suspecting that, but the same happens with digital inputs. I'm 99% sure it's not the switches, because I tested them with a multimeter. I feel like this is something obvious, and I'm just stupid (well I am, but you get the point).

What is connected to those inputs?

@EdgarBonet switches, but just to see if it works, I just bridge the connection with a cable.

INPUT means no internal pullup => super high input resistance == radio antenna. Read something about "floating inputs"

so should I do INPUT_PULLUP instead of just INPUT?

Yes, it means there is about 50k pull up resistor to the Vcc and you can use GND to change it's state to LOW

I changed it to INPUT_PULLUP, and now it's showing mostly 1s, and when I connect it to GND it turns to a 0. I'd rather it would do the opposite, show 0 until I connect it to 5V. INPUT_PULLDOWN said it was undeclared.

That is because not many MCUs have internal pull-downs. On Uno you'll need INPUT + external pull down

show 0 until I connect it to 5V. ... why do you want it that way?

There are several possible reasons random values are seen at micro controller inputs when connected to switches. Here are two:

Missing pull up or pull down resistor when using a SPST switch.

Micro controller inputs should not be allowed to float. This can lead to unexpected input states. Instead, inputs should be connected to ground or the micro controller's positive voltage supply usually either directly or though a resistor. It is common to use a pull up resistor when using a SPST switch connected to ground. Or a pull down resistor when using a SPST switch connected to the micro controller's positive voltage supply. Not all micro controllers have pull up or pull down resistors built internally. Some only have one or the other. In these cases an external resistor may be required. Some thought should be given to using micro controllers that do have built in pull up or pull down resistors. The actual resistance value of these built in resistors does vary (may not be carefully controlled). This is fine for the majority of cases. However, if a specific value is needed, it may be best if external resistors were used instead.

Long wires between the micro controller and the switch.

Longer wires are more likely to develop unexpected currents due external electrical noise. It is possible wires are long enough and the environment they are in electrically noisy enough to develop currents that will change the voltage across a pull up or pull down resistor. And, in turn, change the value of the micro controller's input. The higher the resistor value the more likely this will happen. However, the lower the resistor value chosen the more power needed when the SPST switch is closed. This is usually a concern when operating on batteries. There are many aspects to mitigating the effects of electrical noise. And will take us off subject. Instead, if long wires are necessary, consider using a "brake-before-make" SPDT switch which will connect the micro controller's input pin directly to ground or the micro controller's positive supply voltage. This will require running 3 rather than 2 wires to the switch.
Last words: Take care not to connect pull up resistors or switches to voltages higher than the micro controller's positive supply voltage! Some Arduino boards regulate higher voltages to lower voltage before supplying power to the micro controller. For instance, an Arduino board that runs from the 5 Volt USB power source may have a micro controller which actually runs at 3.3 Volt. In such a case, use the 3.3 Volts supplied to the micro controller when connecting a pull up resistor or switch.


text:
Problem with sending a GET request using the WiFiEsp library
Hello I am trying to make a request using WiFiEsp library but even the examples not working, I have searched a lot but never solved it. most of the solutions are outdated and do not solve anything, I am using Arduino Mega 2560 and ESP8266
the problem as shown in the log is that it's not connected to google.com and I have tried my APIs and I got the same response.
code:
/*
 WiFiEsp example: WebClient

 This sketch connects to google website using an ESP8266 module to
 perform a simple web search.

 For more details see: http://yaab-arduino.blogspot.com/p/wifiesp-example-client.html
*/

#include "WiFiEsp.h"

// Emulate Serial1 on pins 6/7 if not present
#ifndef HAVE_HWSERIAL1
#include "SoftwareSerial.h"
SoftwareSerial Serial1(6, 7);  // RX, TX
#endif
char ssid[] = "IOT";          // name
char pass[] = "60606060";     // password
int status = WL_IDLE_STATUS;  // the Wifi radio's status

char server[] = "www.google.com";

// Initialize the Ethernet client object
WiFiEspClient client;

void setup() {
  // initialize serial for debugging
  Serial.begin(115200);
  // initialize serial for ESP module
  Serial1.begin(9600);
  // initialize ESP module
  WiFi.init(&Serial1);

  // check for the presence of the shield
  if (WiFi.status() == WL_NO_SHIELD) {
    Serial.println("WiFi shield not present");
    // don't continue
    while (true)
      ;
  }

  // attempt to connect to WiFi network
  while (status != WL_CONNECTED) {
    Serial.print("Attempting to connect to WPA SSID: ");
    Serial.println(ssid);
    // Connect to WPA/WPA2 network
    status = WiFi.begin(ssid, pass);
  }

  // you're connected now, so print out the data
  Serial.println("You're connected to the network");

  printWifiStatus();

  Serial.println();
  Serial.println("Starting connection to server...");
  // if you get a connection, report back via serial
  if (client.connectSSL(server, 443)) {
    Serial.println("Connected to server");
    // Make a HTTP request
    client.println("GET / HTTP/1.1");
    delay(100);
    client.println("Host: www.google.com");
    delay(100);

    client.println("Connection: close");
    delay(100);

    client.println();
  }
}

void loop() {
  // if there are incoming bytes available
  // from the server, read them and print them
  while (client.available()) {
    char c = client.read();
    Serial.write(c);
  }

  // if the server's disconnected, stop the client
  if (!client.connected()) {
    Serial.println();
    Serial.println("Disconnecting from server...");
    client.stop();

    // do nothing forevermore
    while (true)
      ;
  }
}

void printWifiStatus() {
  // print the SSID of the network you're attached to
  Serial.print("SSID: ");
  Serial.println(WiFi.SSID());

  // print your WiFi shield's IP address
  IPAddress ip = WiFi.localIP();
  Serial.print("IP Address: ");
  Serial.println(ip);

  // print the received signal strength
  long rssi = WiFi.RSSI();
  Serial.print("Signal strength (RSSI):");
  Serial.print(rssi);
  Serial.println(" dBm");
}

and this is the log
23:21:51.468 -> ----------------------------------------------
23:21:51.468 -> >> AT+CIFSR
23:21:51.533 -> +CIFSR:STAIP,"192.168.1.4"
23:21:51.533 -> +CIFSR:STAMAC,"e8:db:84:df:8b:46"
23:21:51.575 ->
23:21:51.575 -> OK
23:21:51.575 -> ---------------------------------------------- > 192.168.1.4!h=
23:21:51.575 ->
23:21:51.575 -> IP Address: 192.168.1.4
23:21:51.575 -> > getCurrentRSSI
23:21:51.575 -> ----------------------------------------------
23:21:51.575 -> >> AT+CWJAP?
23:21:51.607 -> +CWJAP:"IOT","b4:f5:8e:b5:2f:d9",1,-51
23:21:51.653 ->
23:21:51.653 -> OK
23:21:51.653 -> ---------------------------------------------- > 512
23:21:51.653 ->
23:21:51.653 -> Signal strength (RSSI):-512 dBm
23:21:51.653 ->
23:21:51.653 -> Starting connection to server...
23:21:51.653 -> [WiFiEsp] Connecting to www.google.com
23:21:51.653 -> > startClient www.google.com 443
23:21:51.653 -> ----------------------------------------------
23:21:51.653 -> >> AT+CIPSSLSIZE=4096
23:21:51.700 ->
23:21:51.700 -> OK
23:21:51.700 -> ---------------------------------------------- > 0
23:21:51.700 ->
23:21:51.700 -> ----------------------------------------------
23:21:51.700 -> >> AT+CIPSTART=3,"SSL","www.google.com",443
23:21:52.018 ->
23:21:52.018 -> ERROR
23:21:52.018 -> ---------------------------------------------- > 1
23:21:52.018 ->
23:21:52.018 -> > getClientState 3
23:21:52.018 -> ----------------------------------------------
23:21:52.050 -> >> AT+CIPSTATUS
23:21:52.050 -> 3,CLOSED
23:21:52.050 -> STATUS:4
23:21:52.050 ->
23:21:52.050 -> OK
23:21:52.050 -> No start tag found: 0
23:21:52.050 -> ---------------------------------------------- >
23:21:52.092 ->
23:21:52.092 -> Not connected
23:21:52.092 ->
23:21:52.092 -> Disconnecting from server...

AT firmware doesn't support TLS 1.3 encryption used by most sites now.. try Jiri Bilek's 'fake' AT firmware https://github.com/JiriBilek/ESP_ATMod Best with my WiFiEspAT library


text:
Arduino Uno error resp=0x27
I use the Chinese copy of board. My code is right, but when i upload to board, it print me this:
avrdude: stk500_recv(): programmer is not responding
avrdude: stk500_getsync() attempt 1 of 10: not in sync: resp=0x27
avrdude: stk500_recv(): programmer is not responding
avrdude: stk500_getsync() attempt 2 of 10: not in sync: resp=0x27
avrdude: stk500_recv(): programmer is not responding
avrdude: stk500_getsync() attempt 3 of 10: not in sync: resp=0x27
avrdude: stk500_recv(): programmer is not responding
avrdude: stk500_getsync() attempt 4 of 10: not in sync: resp=0x27
avrdude: stk500_recv(): programmer is not responding
avrdude: stk500_getsync() attempt 5 of 10: not in sync: resp=0x27
avrdude: stk500_recv(): programmer is not responding
avrdude: stk500_getsync() attempt 6 of 10: not in sync: resp=0x27
avrdude: stk500_recv(): programmer is not responding
avrdude: stk500_getsync() attempt 7 of 10: not in sync: resp=0x27
avrdude: stk500_recv(): programmer is not responding
avrdude: stk500_getsync() attempt 8 of 10: not in sync: resp=0x27
avrdude: stk500_recv(): programmer is not responding
avrdude: stk500_getsync() attempt 9 of 10: not in sync: resp=0x27
avrdude: stk500_recv(): programmer is not responding
avrdude: stk500_getsync() attempt 10 of 10: not in sync: resp=0x27
Failed uploading: uploading error: exit status 1

Do you know, what is it?

It could be a number of things that we haven't enough information to diagnose. But 'not responding' is quite likely the result of the wrong- or no port or board being selected, or failure of the connection to your computer, or failure of your operating system to recognize the board.
Editing more information into your question would help: What board & chip (is it an Uno clone?), your OS, whether your board was or wasn't recognized by the OS (Windows) or the IDE (macOS), whether you've installed a CH340 or other alternative USB driver if your board requires it (most Chinese Uno clones require some version of the CH340 driver; macOS usually has it built in; Windows usually doesn't). Do some more digging and flesh out your question a lot more - you'll be able to get much better help. And you may not even need it by then!

Ok, thank you very much!


text:
Declaration of global variables in separate file: compiler conflict
So I have:
1/ My myapp.ino file, that includes src.h (implemented in src.cpp). Compiled for Arduino Uno.
2/ I also have a unit-tests.cpp file that is meant to test functions in src.cpp. Compiled for desktop/MacOS.
I don't understand where to declare global variables. They have to be accessed by those three files (I know it's not 100% good practice but it's a simple app).
Simplified example:
src.h
#ifndef CHAOS_SRC_H
#define CHAOS_SRC_H

extern float min_delta;
extern float max_delta;
extern float min_val;
extern float max_val;
extern float rescale_power;

#endif

src.cpp
#include "src.h"

//float min_delta;
//float max_delta;
//float min_val;
//float max_val;
float rescale_power;

myapp.ino
#include "src.h"

float presets[4][5] =  {
  // MIN_DELTA, MAX_DELTA, MIN_VAL, MAX_VAL
  {0, 500, 0, 30, 1}, // Old tape
  {200, 2000, 0, 255, 1}, // Broken tape
  {0, 500, 90, 100, 3}, // New broken tape (delay time at ~ min)
  {0, 100, 90, 140, 3}, //
};

float min_delta = presets[PRESET][0];
float max_delta = presets[PRESET][1];
float min_val = presets[PRESET][2];
float max_val = presets[PRESET][3];
float rescale_power = presets[PRESET][4];

unit-tests.cpp
#include "src.h"

int main()
{
}

When I compile myapp.ino for Arduino, the compiler complains rescale_power has multiple definitions. So I remove it in src.cpp and it works.
But then, when I compile unit-tests.cpp for desktop, that one compiler complains about Undefined symbols for architecture x86_64:  "_rescale_power".
Re-adding it solves it.
And so on.
What is the way to go please? Any kind of logic?

Why downvote please?

Not sure, but recently questions have been downvoted than usual.. The question is up for closure, probably on the grounds that it's more of a C++ question than an Arduino one. I can't tell which thing you're confused about. Error will point out each of the multiple definitions. You've been using extern. Do you understand the significance of extern in the way that you're using it?

Isn't it the only way to make the variable accessible from outside?

And Arduino and g++ compilers and not reacting similarly, so I'm guessing there must be something specific about Arduino.

Defining a variable multiple times as you have in the shown code will break g++ (or any other c++ compiler for that matter) whether it is launched from the build process or from a more traditional non-Arduino build system. To be clear, I am only telling you that this the wrong tree to bark up. Check Edgar Bonet's answer again, with an understanding that extern will cause variables to be only declared and not also defined as they are by default.

When you have a header/implementation pair of files, the general rule is
that the implementation defines everything that the header declares.
Thus, you keep the definition of rescale_power in src.cpp. Since every
variable should be defined only once, you have to remove the definition
from myapp.ino.
If for some reason src.cpp cannot know the initial value you would want
to give to rescale_power, then live it default-initialized, and assign
the value you want in myapp.ino:
void setup() {
    rescale_power = presets[PRESET][4];
}

Edit: In a comment, you wrote:

I don't get why I can't put rescale_power = 4 in myapp.ino outside
a function ?

Because it's an assignment. Assignments are statements: they are
executed at run time, and can only be written within functions. For
reference, here are the syntaxes for a declaration, a definition and an
assignment:
// Declaration:
extern float rescale_power;

// Definitions:
float rescale_power;      // implicitly zero-initialized
float rescale_power = 2;  // with explicit initialization

// Assignment:
rescale_power = 4;

Thanks for your answer. I removed the declaration from everywhere except src.php. It works for unit-tests.cpp ; but it doesn't work for myapp.ino: error: 'rescale_power' was not declared in this scope.

@theredled: Did you keep the declaration of rescale_power in src.h? Is this file still included in myapp.ino?

No, I removed it. Now I have a declaration in src.h extern float rescale_power;, a definition in src.cpp float rescale_power = 2;.
Now it works! But I don't get why I can't put rescale_power = 4 in myapp.ino outside a function ?

Edited----------


text:
ESP8266 - Where to find pin assignment guide for uploading code?
I try to upload a script which starts a webserver on the ESP8266 with a simple web GUI where the user can enter his WLAN credentials.
/*  ============================================================================================================

    Sample code to create a setup web portal using a soft access point on an ESP8266.

    For more info, please watch my video at https://youtu.be/1VW-z4ibMXI

    MrDIY.ca

============================================================================================================== */

#include <ESP8266WiFi.h>
#include <ESP8266WebServer.h>
#include <EEPROM.h>
ESP8266WebServer    server(80);

struct settings {
  char ssid[30];
  char password[30];
} user_wifi = {};

void setup() {

  EEPROM.begin(sizeof(struct settings) );
  EEPROM.get( 0, user_wifi );

  WiFi.mode(WIFI_STA);
  WiFi.begin(user_wifi.ssid, user_wifi.password);

  byte tries = 0;
  while (WiFi.status() != WL_CONNECTED) {
    delay(1000);
    if (tries++ > 30) {
      WiFi.mode(WIFI_AP);
      WiFi.softAP("Setup Portal", "mrdiy.ca");
      break;
    }
  }
  server.on("/",  handlePortal);
  server.begin();
}

void loop() {

  server.handleClient();
}

void handlePortal() {

  if (server.method() == HTTP_POST) {

    strncpy(user_wifi.ssid,     server.arg("ssid").c_str(),     sizeof(user_wifi.ssid) );
    strncpy(user_wifi.password, server.arg("password").c_str(), sizeof(user_wifi.password) );
    user_wifi.ssid[server.arg("ssid").length()] = user_wifi.password[server.arg("password").length()] = '\0';
    EEPROM.put(0, user_wifi);
    EEPROM.commit();

    server.send(200,   "text/html",  "<!doctype html><meta charset='utf-8'><meta name='viewport' content='width=device-width, initial-scale=1'><title>Wifi Setup</title>
Wifi Setup

Your settings have been saved successfully!
Please restart the device.
" );
  } else {

    server.send(200,   "text/html", "<!doctype html><meta charset='utf-8'><meta name='viewport' content='width=device-width, initial-scale=1'><title>Wifi Setup</title>    <form action='/' method='post'>
Wifi Setup

SSID<input type='text' class='form-control' name='ssid'>

Password<input type='password' class='form-control' name='password'>

<button type='submit'>Save</button>
mrdiy.ca
</form> " );
  }
}

I try to figure out how I need to connect the ESP8266 WLAN module with my Arduino Uno in order to be able to upload that script. I've searched the documentation, but I can't find much helpful.
The module has these pins:
3V3 | RX
RST | IO0
EN  | IO2
TX  | GND

But in the documentation there are other pins which I don't have and the pin EN is not even mentioned in the documentation.
I connected it like this (i did not used pull up resistors yet):
[ESP8266 -> Arduino Uno]

3V3 -> 3V3 (bread board)
EN  -> 3V3 (bread board)
RX  -> RX
TX  -> TX
GND -> GND

The connection works and it responds to AT commands.
But if I try to upload a script, then it fails with:
. Variables and constants in RAM (global, static), used 28236 / 80192 bytes (35%)
║   SEGMENT  BYTES    DESCRIPTION
╠══ DATA     1504     initialized variables
╠══ RODATA   1020     constants
╚══ BSS      25712    zeroed variables
. Instruction RAM (IRAM_ATTR, ICACHE_RAM_ATTR), used 59535 / 65536 bytes (90%)
║   SEGMENT  BYTES    DESCRIPTION
╠══ ICACHE   32768    reserved space for flash instruction cache
╚══ IRAM     26767    code in IRAM
. Code in flash (default, ICACHE_FLASH_ATTR), used 239164 / 1048576 bytes (22%)
║   SEGMENT  BYTES    DESCRIPTION
╚══ IROM     239164   code in flash
esptool.py v3.0
Serial port COM4
Connecting........_____....._____....._____....._____....._____....._____....._____

A fatal esptool.py error occurred: Failed to connect to ESP8266: Invalid head of packet (0xF0)

How do I need to connect my module in order to upload code?
I am using this chip. I also tested another chip (i got 4) to check if mine is broken, but I get the same error.

if you are seeing AT commands  then it is connected correctly ... the ESP-01 is preprogrammed with the AT firmware and I'm not certain if it's capable of accepting a program

try this https://www.instructables.com/HOW-TO-UPLOAD-PROGRAM-TO-ESP-01-USING-ARDUINO/

I followed the instructions. Uploading was successfull after I set the Reset of my Arduino to GND. But now my ESP8266 does not work anymore, there is no WLAN connection and it stopped responding to AT commands.

The sketch replaced the AT firmware. You have an esp-01. It is not a development board but a WiFi module, so it doesn't have an USB adapter and auto reset.

@Juraj wow ok, how do I recognize if a board is for development, I thought each one is? Im a arduino beginner, sorry. What can you even do with such a module as mine if you can't program it?

USB connector is a good indicator of a development board. \ you can program an esp-01. you did it. just you need a way to connect it to a computer and you have to know how to put it in bootloader mode. a simplest esp8266 development board is the Wemos D1 mini.

Ok thx, so there is no safe way to know wheter or not a board supports custom development?

The module is built around esp8266ex microcontroller. In order to make it enter into the flash programming mode the following steps must be taken.

Put mcu into reset state by pulling reset line low.

Pull gpio15 low and gpio0 low while still holding reset low.

Release reset, so it will go high and mcu will restart.

While starting the mcu will check pin states (gpio15 low=use spi flash 25xx series pre-attached to gpio6-11, gpio0 low=self programming mode, gpio2 is NOT low) and will enter the waiting state in a few milliseconds.

Release gpio0 and start data transfer to h/w uart0 (attached to gpio1 and gpio3, aka tx and rx).

So you need to ensure that: gpio0 is pulled up; gpio1 and gpio3 are attached to another host's uart by crossover connection; gpio2 is not low; gpio15 is pulled low; both reset and enable are pulled high; and, of course, you have 3v3 power and ground. Also, you need two push buttons to connect reset and gpio0 to ground temporarily. Then press reset, press gpio0 button, release reset, and, finally, release gpio0. Mcu should now wait for the data to flash. Also, when using esptool you need to tell it to skip auto-reset sequence (--before no_reset), as you're doing it manually.
Considering aforementioned pullups, their presence depends on a module you're using. For esp-01s, they all should be already there (except for the two buttons). For esp-01 (without "s"), you'll need to add pull ups for gpio0 and "chip enable" pin yourself.
There's also auto-programming sequence (which is default for esptool) also sometimes referred as "nodemcu reset method" or such. The idea is that the programming software will switch dtr and rts UART extra signals on and off before data transfer. If you have a small circuit between uart chip and esp8266 mcu that is capable to translate dtr/rts signals to reset/gpio0 states to make mcu to enter self programming mode then you won't need any push buttons anymore.
Such circuit can be made of only two npn transistors and two resistors and is searched online easily. Some boards (including nodemcu, of course) may have such circuit along with usb-ttl converter, dc-dc buck converter and usb plug all on-board. But they are bigger in size and slightly more expensive than esp-01, of course.
Also, for esp-01/esp-01s specifically, you can purchase a prebuilt adapter that provides exactly those missing parts (usb plug, dc buck, two transistor auto-circuit, ttl converter chip, some pullups and female header to plug esp-01 module in). So you can flash your modules using this adapter while sparing some space in your circuit too.
(Hint: the presence of auto programming feature could be guessed from the product photo usually by spotting two sot-23 transistors close to each other).
Or you can buy all these parts and solder such adapter board yourself. This might look a bit too much for a beginner, but, on the other hand, it could make an interesting challenge too.

Thx for your answer! There is no gpio15 on my ESP8266

@Black esp8266 is a microcontroller chip and it does have this one and a bunch of others. Esp-01 is a small board that already includes a pull down resistor from gpio15 to ground. So if you failed to spot it, it's not a big deal as you are not supposed to do anything with that pin yourself. At least, for esp-01.


text:
UART - Different results between logic analyzer and an Arduino
I would like to decode a serial communication.
I have already found out how the protocol works. I can also send serial data with my logic analyzer and control the device this way.
I would like to integrate this function into an Arduino, but my Arduino Mega 2560 throws out completely different serial data than my Logic Analyzer.
The baud rate fits. 230400.
The first byte is 0x42. This is recognized correctly by the Arduino. After that, unfortunately, only gibberish comes out.
Does anyone have any idea how I can approach the problem?

What is the voltage of the signal? Which arduino pins are you using?

5V - Pin 18/19 (TX1/RX1)

In that case, simply attempt to read multiple bytes into a buffer.

It is better to post the code as text rather than a picture.  There's a formatting button in the question editor to properly format the code when you insert it.  Since the output is text, you can put it in the question the same way you do the program code.

@Abel I hate myself for that. I had measured the voltage. 5V.
I then ordered a Mega 2560 especially for this project because I didn't want to build a voltage divider.
Whatever I measured was wrong. The voltage is 3.3V.
I've been at it for half a day now. Such an unnecessary mistake.
Thanks for the hint.

@Jens1888 ATmega2560 data sheet says minimum Vih is 0.6Vcc so with 5V supply it should see a 3.3V signal just fine.

You get the first byte correctly but miss the next bytes because you are busy printing out the first byte instead of receiving the following bytes.
Your code cannot to all that at once, especially if you are using Arduino libraries like that.
This is the upsides and downsides of Arduino, it lets you do simple things easily, but either your requirements already grew out of being simple and suitable for Arduino, or you are using the Arduino libraries without considering what they are capable of and how.
So instead of waiting for first byte and immediately printing it out, it might make more sense to wait and read bytes until you have read some whole packet and have enough time to print the bytes before next byte arrives.
Another thing, how do you even know your Arduino can use 230400 bps rate? If it uses a 16 MHz clock source, you cannot get exacltly 230400 but the closes baud rate is 222222 bps, and that is already a 3.55% error to what you need. Usually the target is better than 1% error, but in a pinch many devices might work within 2% error because in theory it allows both devices to be within 2% of the nominal rate. Having an error of 3.5% is usually too large and very close to the point of not working at all.
Edit: OK, it cannot be a software issue because Arduino UART does use interrupts and uses a ring buffer for buffering data.
What is known is that a 16 MHz AVR cannot exactly hit 230400 bps and will have 3.5% error in the baud rate which exceeds recommendations for maximum baud rate error. What even makes the situation worse is that instead of a more precise crystal, the Arduino Mega2560 uses a ceramic resonator with additional 0.5% tolerance, 0.3% temperature stability, and 0.2% aging. A crystal would have in any case better than 0.01% tolerance for all scenarios. So the most likely cause is that the Arduino Mega2560 can be simply said not to support baud rate of 230400 reliably so that is why it does not work.
And also the Mega256 data sheet says that minimum input high voltage is 0.6*Vcc, so using a 5V MCU that will be 3.0V minimum, so it will be within specification to receive a 3.3V signal. So the voltage issue is extremely unlikely.

The Arduino Mega 2560 had a 64Byte Buffer for that. This allows the loop to run without interrupting the serial reception.

@Jens1888 Please explain where this 64 byte buffer is? It is not in the MCU for sure. Do you mean on the USB UART? Or is this a feature of Arduino code to provide you interrupt reception and transmission with a 64 byte buffer in code?

I don't know exactly how the buffer is realized. However, there is one.
Its a Arduino Feature for all Serial Comms.
https://www.arduino.cc/reference/en/language/functions/communication/serial/available/

@Jens1888 If there is no source code for the libraries, nobody knows how it really works. I do not understand why the Arduino libraries deliberately want to hide all the important stuff how it works so you can't see why it does not work when it does not work. But in this case it must use interrupts to read data into ring buffer. But I have never investigated how it receives data if baud rate mismatch causes framing errors.

@Justme: Here is the AVR implementation of the Arduino core. The “RX complete” ISR is implemented in HardwareSerial_private.h. Other bits of the serial communication library are in the other files named HardwareSerial*.

You need to understand the MCU you are using to be able to test and diagnose that the functionality meets your needs.

The accuracy of the baud/bit rate has to be considered for EACH serial link. In this case you have the serial link to your external device and the serial link to the Arduino console (a serial to USB converter implemented in an ATMEGA8).
Here is a good link to understand the problem of baud/bit rate generation: https://wormfood.net/avrbaudcalc.php

Notice here that you cannot actually set 230.4k because of the rough granularity as UBRR approaches 1.
You actually get 250k baud, which is used often for serial addressed DMX peripherals and works well on most Arduino variants.  In you case however, this is you first problem, a mismatch between your peripheral bit rate and the Arduino 2560.

There will be a difference between the baud/bit rate for your two serial connection since the console serial link is defined in a separate MCU (the ATMEGA8) and they have different crystals. You should examine the schematic for the Arduino Mega 2560 and try to understand the configuration.

Here there is an obvious answer to most of your problem, and that is to eliminate one of the two serial connections. You already discovered that the Arduino Zero works successfully, you just didn't go on to discover why (and it's not the clock rate for the MCU that is the issue).
In several Arduino variants they have a direct USB peripheral controller built in. Look at the Arduinos that use the ATMEGA32u4 or as you found the more modern variants such as the Arduino Zero. In these variants the console transfer actually happens at USB speeds for the serial transfer, this is a rate fixed at the USB connection state rate.
You should experiment with raising the baud/bit rate on the console higher than the peripheral bit rate you are using, that may solve your immediate problem with the MEGA 2560. I'd suggest you try setting the console to 500k or 1M, this may depend on what your IDE device is (PC or Linux) allows configuration for of course.
My suggestion would be to move to an MCU with inbuilt USB.

The Arduino core sets the UART to double speed mode (U2Xn = 1) when possible. For 230.4 kb/s, you get UBRR = 8, and an actual baud rate of 222.2 kb/s, (error = −3.5%). Not as bad as the 8.5% error you are showing, but still worrisome. 2. The two MCUs on the board (ATmega2560 and ATmega16U2) have the same type of UART, clocked at the same frequency. Their baud rate errors may be large, but they will match, ensuring trouble-free communication between them.

@EdgarBonet, agreed on U2XN, but it's still a sizeable error rate assuming the crystals are exactly the same frequency. In actuality the two crystals will differ slightly which could easily add another +/-1% variance. As I said, for the Arduino Mega 2560 with two separate async channels (one to the peripheral and one to the USB/serial converter it would be beneficial to raise the baud rate on the console uplink.

At that baud rate you have 23Kcps, giving you ~40us for each loop invocation.  IIRC the default serial buffer length is 16 characters, and you don't comment on the speed of the serial interface you are using for println() relative to the incoming data rate.  It is therefore possible that you might be simply getting behind on the incoming stream.
Your question asks for an approach to diagnosing.
If possible I'd start by changing the input stream to have the same bitrate, but with the characters spaced well apart.  See if that works.
If it does, the issue is likely either tied to loop timing and responsiveness, or could be related to the crystal/PLL accuracy at that rate.  (If may simply be the clock rate isn't a good match for the baudrate generator, with drift building up after the first character.)

I don't know how else to confirm a solution here. @Abel gave the decisive hint. I measured the voltage of the signal incorrectly.
Edit: I can't accept my own answer as a solution for another 2 days.

Actually it does not matter. The problem may be elsewhere. If you received the first byte correct, the voltage might just not be the issue, but your Arduino not buffering the data for you, or the fact that it cannot reach the required 230400 bit rate without too much error. The Mega2560 data sheet says at 5V, a digital input will see 3.0V reliably as logic high, so this may be the least of your issues.

I use an Arduino Zero that runs on 3.3V and it works perfectly.

You cannot compare those two. Of course a 32-bit ARM MCU running at 48 MHz clock can set the baud rate more precisely than 8-bit AVR running at 16 MHz. I believe the voltage of the MCU is not the problem, but hitting the correct baud rate. So simply because using an Arduino Zero works, it still does not prove it was a voltage problem to begin with.

That makes sense.
As already written, the 2560 should recognize the 3.3V as HIGH.