text:
Servo doesn't move if I detach it AFTER the write
This is a bit weird, and I don't understand anything.
Basically, I'm just playing with my servo. I wrote a small program, which can be found at this link: https://pastebin.pl/view/8e9c9573 (Note: It's three files, I left some comments there, and the idk function is just my last resort, trying to separate myself from loop, I really don't know :/ ).
So I run controller.Setup() in the setup function, and then in loop I just move it to 180 and detach it, then I run into an infinite loop. Note: I know it's not very good code, but that's not what concerns me right now.
The problem is, when I add the call to detach (line 22), the previous move doesn't run! I think I'm going crazy, cause as soon as I remove the line and recompile, it actually moves.
I tried to remove the lock(Controller::m_Attached), and it still doesn't work. Please let me know if I didn't notice something, but I really don't understand.
Notes:

I'm using arduino-cli, here's my not-very-perfect Makefile: https://pastebin.pl/view/daa852ff
I use the Servo library: https://www.arduino.cc/reference/en/libraries/servo/
I'm using an Arduino Uno

EDIT:
Someone told me to post the code in the question, so here I go:
//Main.ino
#include <Servo.h>
#include "Controller.h"

Controller controller(3);

void idk();

void setup() {
    Serial.begin(9600);
    controller.Setup();
}

void loop() {
    idk();
    while(true);
}

void idk() {
    controller.Move(180);
    controller.Unlock();
}

// Controller.h
#pragma once
#include <Servo.h>

class Controller
{
public:
    Controller(int servoPin)
        : m_ServoPin(servoPin), m_Attached(false) {}

    void Setup();
    void Move(int angle);

    void Lock();
    void Unlock();

private:
    Servo m_Servo;
    bool m_Attached;
    const int m_ServoPin = 3;
};

// Controller.ino
#include "Controller.h"

void Controller::Setup()
{
    m_Servo.attach(m_ServoPin);
    m_Attached = true;
    Serial.print("[CONTROLLER] Attached Servo\n");
}

void Controller::Move(int angle)
{
    if (m_Attached)
        m_Servo.write(angle);
}

void Controller::Lock() {
    m_Servo.attach(m_ServoPin);
    m_Attached = true;
}

void Controller::Unlock() {
    m_Servo.detach();
    m_Attached = false;
}

the detach() function probably stops the data pin from outputting the servo control signal ... you are disabling the control signal a few microseconds after you enable it, so it is never generated ... furthermore, a servo requires the signal to be present at all times

@jsotola Thank you sooo much. When I add a delay in between the function calls it works. You should make it an answer so that I can accept it

The detach() function probably stops the data pin from outputting the servo control signal.
Your code disables the control signal a few microseconds after it is enabled.
The cotrol signal is never generated.
Furthermore, a servo requires the signal to be present at all times for it to keep its position.
When your programming includes real-world events, you have to think about the time frame of the events, and about the time frame of the running program.
Think in the terms that the program can loop 100,000 times before the servo has finished moving.

Attach and Detach do little except intialise or deintialise variable in the servo library functions and may move the servo to a central position.
The function needs to know which pin to use to drive the servo.
Once the servo is attached when you do a servo.write it will send a pulse to the pin.
You could do this yourself
    int servopin=8;
    pinMode (servopin, OUTPUT);
    digitalWrite(sevopin,LOW);  // makes sure there is no pulse yet

      // more code
    digitalWrite(servopin,HIGH);
    delayMicroseconds(1500);      // 1500 will set the servo to
    digitalWrite(servopin,LOW);    // mid position
    delay(19);    // gives time for the move can be unblocking code

This can be repeated to provide a continuous pulse. For situations where there is no or minimal load a servo may not move if the pulses stop. If you repeat the pulses with sithout the delay then some will be ignored. If say you are increasing the Microsecond delay to sweep the servo across and miss the delay after the pulse you will find it jumps serveral steps this applies if you use servoWrite without a pause too.
Once you do a detach the servo library function will not know which pin the servo is using.

attach() does more than just initialize a variable: it starts a continuous stream of pulses at 50 Hz. And write() doesn't send a single pulse: it changes the width of all the subsequent pulses of the stream. These pulses are interrupt-driven, so you don't have to worry about program timing.


text:
esp32s: error: 'WDT_TIMEOUT' was not declared in this scope
I am trying to initialize the watchdog timer.
I have installed
arduino-esp32-master.zip

I have
#include <esp_task_wdt.h>

set but it is not highlighted red indicating the IDE knows about it.
The error indicates that a major function is not present.
full error:
Arduino: 1.8.13 (Linux), TD: 1.53, Board: "ESP32 Dev Module, Disabled, Default 4MB with spiffs (1.2MB APP/1.5MB SPIFFS), 240MHz (WiFi/BT), QIO, 80MHz, 4MB (32Mb), 115200, None"

/home/brad/Documents/bradcode/Arduino/esp32s-infrared-ac-wifi-server-v4/esp32s-infrared-ac-wifi-server-v4.ino: In function 'void setup()':
esp32s-infrared-ac-wifi-server-v4:229:23: error: 'WDT_TIMEOUT' was not declared in this scope
     esp_task_wdt_init(WDT_TIMEOUT, true); //enable panic so ESP32 restarts
                       ^
Multiple libraries were found for "IRremote.h"
 Used: /home/brad/Documents/bradcode/Arduino/libraries/IRremote
 Not used: /home/brad/Documents/bradcode/Arduino/libraries/Arduino-IRremote-master
 Not used: /home/brad/Documents/bradcode/Arduino/libraries/IRremote-2.8.1
Multiple libraries were found for "WiFi.h"
 Used: /home/brad/.arduino15/packages/esp32/hardware/esp32/1.0.4/libraries/WiFi
 Not used: /home/brad/Downloads/arduino-1.8.13/libraries/WiFi
 Not used: /home/brad/Documents/bradcode/Arduino/libraries/WiFiEspAT
exit status 1
'WDT_TIMEOUT' was not declared in this scope

This report would have more information with
"Show verbose output during compilation"
option enabled in File -> Preferences.

What library did I fail to install to get the watchdog timer initialized?
UPDATE:
My additional boards URLs
https://raw.githubusercontent.com/espressif/arduino-esp32/gh-pages/package_esp32_index.json,http://arduino.esp8266.com/stable/package_esp8266com_index.json

After following recommendations for poster, I got past that error and hit another one right away.
Arduino: 1.8.13 (Linux), TD: 1.53, Board: "ESP32 Dev Module, Disabled, Default 4MB with spiffs (1.2MB APP/1.5MB SPIFFS), 240MHz (WiFi/BT), QIO, 80MHz, 4MB (32Mb), 115200, None"

In file included from /home/brad/Documents/bradcode/Arduino/esp32s-infrared-ac-wifi-server-v4/esp32s-infrared-ac-wifi-server-v4.ino:24:0:
/home/brad/.arduino15/packages/esp32/hardware/esp32/1.0.4/libraries/WebServer/src/WebServer.h: In member function 'virtual size_t WebServer::_currentClientWrite_P(const char*, size_t)':
/home/brad/.arduino15/packages/esp32/hardware/esp32/1.0.4/libraries/WebServer/src/WebServer.h:144:83: error: 'class WiFiClient' has no member named 'write_P'
   virtual size_t _currentClientWrite_P(PGM_P b, size_t l) { return _currentClient.write_P( b, l ); }
                                                                                ^
/home/brad/Documents/bradcode/Arduino/esp32s-infrared-ac-wifi-server-v4/esp32s-infrared-ac-wifi-server-v4.ino: In function 'void setup()':
esp32s-infrared-ac-wifi-server-v4:246:10: error: 'class WiFiClass' has no member named 'mode'
     WiFi.mode(WIFI_STA);
          ^
esp32s-infrared-ac-wifi-server-v4:246:15: error: 'WIFI_STA' was not declared in this scope
     WiFi.mode(WIFI_STA);
               ^
esp32s-infrared-ac-wifi-server-v4:251:73: error: no matching function for call to 'WiFiClass::config(IPAddress&, IPAddress&, IPAddress&, IPAddress&, IPAddress&)'
     if (!WiFi.config(local_IP, gateway, subnet, primaryDNS, secondaryDNS)) {
                                                                         ^
In file included from /home/brad/Documents/bradcode/Arduino/esp32s-infrared-ac-wifi-server-v4/esp32s-infrared-ac-wifi-server-v4.ino:22:0:
/home/brad/Documents/bradcode/Arduino/libraries/WiFiEspAT/src/WiFi.h:72:8: note: candidate: bool WiFiClass::config(IPAddress, IPAddress, IPAddress, IPAddress)
   bool config(IPAddress local_ip, IPAddress dns_server = INADDR_NONE, IPAddress gateway = INADDR_NONE, IPAddress subnet = INADDR_NONE);
        ^
/home/brad/Documents/bradcode/Arduino/libraries/WiFiEspAT/src/WiFi.h:72:8: note:   candidate expects 4 arguments, 5 provided
Multiple libraries were found for "IRremote.h"
 Used: /home/brad/Documents/bradcode/Arduino/libraries/IRremote
 Not used: /home/brad/Documents/bradcode/Arduino/libraries/IRremote-2.8.1
 Not used: /home/brad/Documents/bradcode/Arduino/libraries/Arduino-IRremote-master
exit status 1
'class WiFiClass' has no member named 'mode'

This report would have more information with
"Show verbose output during compilation"
option enabled in File -> Preferences.

I have some library mixed up still

What do you mean you have "installed" arduino-esp32-master.zip? You don't install these things - you put the JSON URL in the preferences and install the board definitions using the boards manager.

@Majenko
I updated the post with my URLs. I should have the correct ones already loaded.

There is no such macro in the ESP32 core. That parameter is just the number of seconds before a timeout occurs. Just pick a reasonable value. 5 seconds seems to be a commonly used (and appears to be used in the core) value.

setting the variable the line above caused the same error. So I deleted the variable all together and just plugged in the number 5. Now I am at a new error.  'class WiFiClass' has no member named 'mode'. I still have some library all messed up.

I have multiple wifi.h libraries as indicated in the errors posted. I just tried a different one and got past that other new error. Now I'm golden.

source: Stack Exchange

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

sort: votes


text:
How do I make two (or more) pins available on my server url?
I have a webserver configured on my esp8266 with is set to fire off electrical relay0 on my 8 port relay board.
The device initializes relay0 perfectly and without errors.
But when I configure the second relay1, i get no response from my second url.
//note, when you write to low, you turn the switchport on. It's backwards for some reason
#include <ESP8266WiFi.h>
#define statusLed 2   // built-in led for the ESP8266-12

const char* ssid = "myssid";
const char* password = "mypass";

int switchPin0 = 16;
int switchPin1 = 5;
int switch0;
int switch1;

WiFiServer server(80);

void setup() {
  Serial.begin(115200);
  delay(10);

  pinMode(statusLed, OUTPUT);
  pinMode(switchPin0, OUTPUT);
  digitalWrite(switchPin0, HIGH);

  // Connect to WiFi network
  Serial.println();
  Serial.println();
  Serial.print("Connecting to ");
  Serial.println(ssid);

  WiFi.begin(ssid, password);

  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }
  digitalWrite(statusLed, HIGH);
  Serial.println("");
  Serial.println("WiFi connected");

  // Start the server
  server.begin();
  Serial.println("Server started");

  // Print the IP address
  Serial.print("Use this URL : ");
  Serial.print("http://");
  Serial.print(WiFi.localIP());
  Serial.println("/");

}

void loop() {
  // Check if a client has connected
  WiFiClient client = server.available();
  if (!client) {
    return;
  }

  // Wait until the client sends some data
  Serial.println("new client");
  while(!client.available()){
    delay(1);
  }

  // Read the first line of the request
  String request = client.readStringUntil('\r');
  Serial.println(request);

  client.flush();

  // Match the request

  int value = HIGH;
  if (request.indexOf("/SWITCH=0") != -1){
    digitalWrite(switchPin0, LOW);
    digitalWrite(statusLed, LOW);   // blink led
    delay(1);
    digitalWrite(statusLed, HIGH);
    //set water pump time here
    delay(8000);
    digitalWrite(switchPin0, HIGH);
    value = HIGH;
    ++switch0;
  } else if (request.indexOf("/SWITCH=1") != -1){
    digitalWrite(switchPin1, LOW);
    digitalWrite(statusLed, LOW);   // blink led
    delay(1);
    digitalWrite(statusLed, HIGH);
    //set water pump time here
    delay(8000);
    digitalWrite(switchPin1, HIGH);
    value = HIGH;
    ++switch1;
  } else {

    }

  // Return the response
  client.println("HTTP/1.1 200 OK");
  client.println("Content-Type: text/html");
  client.println(""); //  do not forget this one
  client.println("<!DOCTYPE HTML>");
  client.println("");

  client.print("Switch pin is now: ");

  if(value == HIGH) {
    client.print("Off");
  } else {
    client.print("On");
  }
  client.println("

");
  client.println("Switch 0");
  client.println("Click here  to send a measured amount
");
  client.println("Number of times plant 0 has been fed is ");
  client.println(switch0);
  client.println("

");
  client.println("Switch 1");
  client.println("Click here  to send a measured amount
");
  client.println("Number of times plant 1 has been fed is ");
  client.println(switch1);
  client.println("");

  delay(1);
  Serial.println("Client disconnected");
  Serial.println("");
  digitalWrite(statusLed, LOW);   // blink led
  delay(1);
  digitalWrite(statusLed, HIGH);

}

my counter will update, but the relay pin never fires for relay1. relay0 works fine. I can swap the ports and then the second relay will work and not the first. I just can't manage both.
How do I get a second (or more) relay ports to initialize via webpage?

It looks like you forgot to initialize switchPin1 to be an output.
Add the following to your setup() (for example, right after the corresponding initialization commands for switchPin0):
void setup() {
    ....
    pinMode(switchPin1, OUTPUT);
    digitalWrite(switchPin1, HIGH);
    ....
}

wow, what a horrible oversight on my behalf. Thank you. You nailed it.

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


text:
Infared: some controllers send code into infinite loop
I have a piece of code that captures input from infrared and spits it out to the serial port.
When I use it with a simple controller that comes with a typical kit, it receives the infrared code just fine for each button I depress.
But when I try and capture information from my air conditioning remote (the one I need to clone), I receive the first hexcode and then the output gets thrown into an infinite loop with that 1 hexcode, and will not break out.
#include <IRremote.h>

const int RECV_PIN = 7;
IRrecv irrecv(RECV_PIN);
decode_results results;

void setup() {
  Serial.begin(115200);
  irrecv.enableIRIn();
  irrecv.blink13(true);
}

void loop(){
  if (irrecv.decode(&results)) {
    Serial.println(results.value, HEX);
    irrecv.resume();
  }
}

What is causing the infinite loop from "some" controllers and how do I prevent it?
Update:
In changelog they say they renamed RAW_BUF to RAW_BUFFER_LENGTH. I find RAW_BUFFER_LENGTH in IRremoteInt.h and not IRremote.h
I'm not calling on IRremoteInt.h
I did try and reset the buffer from 101 to 201 in IRremoteInt.h, recompiled, uploaded, same issue.

some air conditioners have really long bit sequences ... they can also use error checking

@jsotola That sounds very plausible. How do I capter all of it?

@jsotola  Quilo model QP114

try this to capture all of the bit stream ... https://stackoverflow.com/questions/22751255/how-to-correctly-receive-and-send-raw-ir-data-from-arduino

@jsotola The code from that page performs a much more robust infinite loop, but still the same infinite loop. In the answers they mention #define RAWBUF 100. That does not exist in my IRremote.h

i wonder if you are on the wrong track ... your sketch is an infinite loop ... basically, all arduino sketches are infinite loops

@jsotola so, you're saying that 10 million lines (and counting, very quickly) of https://i.imgur.com/3VU4t39.png is sane?
No, it is not because of the main program loop.


text:
Peculiar relay behavior from POST
I am trying to toggle on/off between two separate HTTP request.
One submit button to turn it on, and another separate submit button to turn it off.
I expect the device to launch in the off/low 0V position
digitalWrite(switchPin2, LOW);
The first submit button would turn the device on/HIGH/sw1, the second submit button would turn it off/LOW/sw2.
But what it is doing is at first nothing when the first/sw1 submit button is pressed but when I press the sw2 submit, I get serial output telling me that sw1 was just pressed. Then if I press sw2 again, it will tell me sw2 was just pressed but will not repeat the cycle until i press sw1 again. Then sw2 becomes functional, just performing the wrong function.
#include <ESP8266WiFi.h>
#include <ESP8266WebServer.h>

ESP8266WebServer server(80);

const char* ssid = "ssid";
const char* password =  "pass";
int switchPin2 = 4;

//counter variable
int switch2;

String inString;

void webpage() {
  server.send(200,
          "text/html",
          " \
           \

Air conditioner manager
 \n\

Turn air conditioner on for "+String(switch2)+" ms
 \
           <form name='frm1 method='post'> \
            <input type='text' name='sw1' value=8000> \
            <input type='submit' value='Submit'> \
           </form> \

Turn air conditioner off for "+String(switch2)+" ms
 \
           <form name='frm2' method='post'> \
            <input type='text' name='sw2' value=8000> \
            <input type='submit' value='Submit'> \
           </form> \
           \
          ");
}

void response() {
  //add additional switch/relay here if adding new plug
  if (server.hasArg("sw1") && (server.arg("sw1").length() > 0)) {
    Serial.print("Switch 1 entered:\t");
    Serial.println(server.arg("sw1"));
    digitalWrite(switchPin2, HIGH);
    Serial.print("\nUnit is on:\n");
    int num = server.arg("sw1").toInt();
    ++switch2;
    server.sendHeader("Location", String("/"), true);
    server.send (302, "text/plain", "");
  } else if (server.hasArg("sw2") && (server.arg("sw2").length() > 0)) {
    Serial.print("Switch 2 entered:\t");
    Serial.println(server.arg("sw2"));
    digitalWrite(switchPin2, LOW);
    Serial.print("\nUnit is off:\n");
    int num = server.arg("sw2").toInt();
    ++switch2;
    server.sendHeader("Location", String("/"), true);
    server.send (302, "text/plain", "");
  } else {
    server.send(400, "text/html", "
HTTP Error 400

Bad request. Please enter a value.
");
  }
}

void setup() {
  Serial.begin(115200);
  pinMode(switchPin2, OUTPUT);
  digitalWrite(switchPin2, LOW);
  WiFi.begin(ssid, password);  //Connect to the WiFi network
  while (WiFi.status() != WL_CONNECTED) { // Wait for connection
    delay(500);
    Serial.println("Waiting to connect...");
  }
  Serial.print("IP address: ");
  Serial.println(WiFi.localIP()); // Print the local IP
  // server.on("/body", handleBody); // Associate the handler function to the path
  server.on("/",HTTP_GET, webpage);
  server.on("/",HTTP_POST,response);
  server.begin(); // Start the server
  Serial.println("Server listening");
}

void loop() {
  server.handleClient(); //Handling of incoming requests
}

I get no error, only erratic output.
How do I toggle on/off between 2 submit buttons?
UPDATE: Serial output.
Waiting to connect...
IP address: 192.168.1.9
Server listening
Switch 1 entered:   8000

Unit is on:
Switch 2 entered:   8000

Unit is off:

are you able to toggle the relay with simple code?

Could you add the Serial output to your question? I do not really unerstand what you are doing (why "POST" request?), so maybe there is something wrong with he communication.

@jstola do you mean like in the sample code where it turns on for a second and then turns off? Yes. That's the code I started with. I'm just splitting that function in half.

@ridgy Just added

Seems like you pressed three times Switch 1 and then once Switch 2... Btw., there is a typo in your HTTML; missing ' in <form name='frm1 method='post'> after frm1 - is this also true in your original code?

Depending on your web browser, there may be a browser console (in Firefox: Developer tools -> Console) where you can see what your browser does send and what answer it gets.

@ridgy That was it! Now it works. A missing quote. Yeesh


text:
Is a PWM phase duration set with OCR1A a reliable way to communicate values to other Arduinos?
I am working on communicating 4 switch states across multiple Arduinos using only one pin. It must be as fast as conceivably possible.
Currently I have a master Arduino reading all 4 switches (multiplexing) and encoding them as 4-bit values: 0001 = 0, 0010 = 1, 0011 = 2 and so on up to 1111 = 15. I am thinking of assigning the low and high pulse duration/width, (+1) to produce a PWM square wave. So 1+0=1, 1+1=2, 1+2=3 ... 1+15=16. The high width (or low width) will hold the muxed value (+1.) Each slave would read this muxed value and demux it to get the state of all 4 switches.
Now to my concern: Is this approach safe and reliable? Or should I triple up the values: 1=3, 2=6, 3=9 ... to build in some tolerance and prevent some time misread due to some miss-interpolations? My switches control motors and a misread could have some unpleasant consequences.
I am using the Arduino's internal crystal, nothing external.
As a side note: I am actuality using Seeeduinos XIAO and not an Arduino. I started working on the timer based PWM writing and reading aspect, but it turns out to be quite complicated as there is not a lot of exaples to be found.

Please define "reliable" in aspects of hardware and software. -- HW: How long are the wires between the reading Arduino and the motor Arduinos? How much interferences do you expect? -- SW: You could use multiple readings in the receivers and a majority decision. -- Radio control servos get their position command by a pulse width, 1 to 2 ms every 20ms. The resolution is 1% or better. Expensive models in delicate conditions (think about high speed airplanes) are controlled by this. So PWM is a way with some reliability.

Why not just use Serial? You can use some pretty fast baud rates reliably and you only need 1 wire for transmission only.

The Arduino PWM output goes from 0 to 255, so you could multiply by 15 for a maximum value of 240 to give a greater margin of error. Though the serial option is better. You could send data packets with CRC/ECC for greater reliability.

Actually, you could do both PWM and serial. The receivers could compare the two and only act if they agree whilst flagging discrepancies.

This is presumably for an e-stop? Would you ever want to e-stoo a single motor? Is binary sufficient here?

@thebusybee You suggestions are exactly the directions I was heading. Thank you for mentioning interference! All wires are under 8 inches and should be hopefully not too close to anything discharging interference.

@Majenko serial is to slow. I want something supper fast.

@tim good point. I think I will be multiplying by 6, which will be giving me a 3 point offset in either direction.

The ATMega328P is capable of 2MBaud. That's 200,000 potential updates of your switches per second. Is that not "super fast" enough? Most of the slowdown of serial is the Arduino's libraries which are inefficient. Access the UART registers directly for extra speediness.

@DaveNewton It is true that a good portion of the logic is e-stop related. Which now gives me the idea of splitting up some of the logic. I could use a superseding e-stop very short pulse, to obtain a faster read, just when the main motor gets turned on. This would dramatically speed up things!

@MeSo2 That's the approach I would take, although in fairness, serial should be plenty fast enough. My view of an e-stop is "U STOPS ALL TEH THINGS NOW!" and post-e-stop comms can do whatever it wants. This also allows the e-stop to be tied to an interrupt pin as if each unit had its own e-stop slap switch. Any post-mortem comms can be handled once the unit is in the e-stop state.

@MeSo2 While I haven't tried anything like this for CNC/life-threatening-car-like-things, I have done it with robots using separate control modules, w/ serial protocols. High-priority msgs were handled extremely quickly, w/ e-stop equivalents handled in <1-2ms (500/sec). For comparison, the SawStop stops in ~5ms (200/sec), airbag deploys are ~50ms (20/sec).

@Majenko Access the UART registers directly ... I did not know you can do that with serial. Having to learn about timers was taxing as is; not sure if I have it in me to learn about UART registers.

In my opinion your timer approach has no benefits over using UART like majenko suggested. If it has to be fast you'd have to measure pulse lengths with high precision and it costs CPU time - even if you use interrupts.


text:
What is the REF pin for -- pin 9 on ATSAMD21G18-QFN48?
32-bit ARM-Based microcontroller SAM D21E / SAM D21G /SAM D21J
I have a Seeeduino XIAO PDF to schematic which uses a ATSAMD21G18-QFN48 chip. Pin D1 on the Seeeduino is pin 9 on the chip; which is labeled as PA4/EIC/REF/AIN4/SCOM0PAD0/TC0.

What would the REF pin be used for; and how would the pin be addressed in the code?
Based on this post is sound like it is ADC related.
There is no indication about this on the https://wiki.seeedstudio.com/Seeeduino-XIAO/ website. Only this image:

PA04 pin can be a normal GPIO or a voltage reference pin (similar to VDDANA). So, the ADC input will be compared to this VREF pin in the application if needed. If you have configured it as GPIO, then it will behave as a normal IO pin. It depends on how you configure it.


text:
Cons of using timer0 with external input?
I'm working on a project of differential drive control in which I use speed encoders for the odometry.
I count the number of rising edges using counter0 and counter5 (on Arduino Mega 2560), which works fine by itself, but when I combine that code with other parts of my code, many things stop working and I can't figure out why. My current guess is that it is related to timer0.
So my question is: what can go wrong when we modify the registers for timer0? I know that delay(), millis(), micros(), and PWM on pins 4 and 13 won't be available anymore, but are there other things that I should be aware of? Are there some libraries that stop working?
If that is the case, I'm thinking of using hardware interrupts for the odometry.
Thanks in advance.
Edit: Here's more information about the project:
In the project, I use a behavior based controller to build a differential drive robot that goes to some goal coordinates while avoiding obstacles.
The speed measurement is done using speed encoders and optocouplers. those values are also used for updating the position and heading of the robot. It runs every 210 milliseconds.
The obstacle distance is measured using 7 ultrasonic sensors that are controlled using pin change interrupts.
The only external libraries that I use are TimerOne.h and TimerThree.h (which do not use timer0) and I made sure not to use timer0 (at least directly) in the parts that I wrote myself.
My code is interrupt-driven, so I wonder if that could also be a cause for the wrong behavior.
Here's the main code
#include "definitions.h"    // contains constants that should be accessible by many files
#include "diff_cntrl.h"     // controls the wheels (left and right speed) uses timer0 and timer5 for speed measurement
#include <TimerThree.h>     // used for generating timer interrupts for the differential control
#include "A7.h"             // used for commmunication using an A7 module through Serial1
#include "M_Ultrasonics.h"  // measures distance from 7 ultrasonic sensors using pin change interrupts on A8 - A14 (PORTK) and TimerOne.h
#include "FuzzyBBC.h"       // a fuzzy logic behavior-based controller (does only floating point computations

volatile double dists[NUM_US]; // array where the obstacle distances will be stored
volatile uint8_t   done = 0;   // flag set by M_Ultrasonics.h when all 7 seven distances are measured
FuzzyBBC fbbc;                 // reference to the behavior based controller

volatile double xG = 0, yG = 0; // coordinates of the goal

volatile double v = 0, w = 0;   // desired velocity and angular velocity. set by fbbc and used by the differential controller

// variables holding the current state of the
volatile double x = 0, y = 0, phi = 0; // coordinates and heading

volatile double dx, dy, dphi;   // changes in coordinates and heading (used for debugging

// variables used for the speed control of the motors: reference speed, actual speed, counter value, output voltage for left and right motors
volatile double l_ref = 0, l_spd = 0, r_ref = 0, r_spd = 0;
volatile uint8_t l_ctr = 0, r_ctr = 0;
volatile uint8_t l_volt = 0, r_volt = 0;

volatile boolean newvolt = true;  // flag set when a new voltage value is computed

volatile boolean updated = false; // flag set to allow transmission of data to the remote machine
volatile uint8_t update_count = 0;

//------------debug variables-----------------
volatile double dvl, dvr;
//--------------------------------------------
void setup()
{
  delay(5000);
  A7begin();    // starts up the A7 module and connects to a predefined remote machine
  initMotors(); // initialize the pins for the motor control (I use an LM293D motor driver)
  setup_cntr(); // set the registers for timer0 and timer5
//  vw2lr();

  fbbc.begin(&xG, &yG, NUM_US, dists, &x, &y, &phi, &v, &w);  // starting the fuzzy logic controller, it has direct access to the provided variables
  HCRS04.begin(T_US, dists, &done);   // starting the ultrasonic sensors controller (it runs every 30 millisecond

  Timer3.initialize(T_MOTOR*1000L);   // timer interrupts for the speed control (T_MOTOR = 210 milliseconds)
  Timer3.attachInterrupt(cntrISR);
}

void loop() {
  if(done)    // wait for obstacle distances to be updated
  {
    arbiter();  // update v and w
    if(updated && !waiting){    // send data to the remote machine
      String info = "v: " + String(v) + "\tw: " + String(w) +
                    "\t\tvl: " + String(l_spd) + "\tlref: " + String(l_ref) + "\tlvolt: " + String(l_volt) +
                    "\t\tvr: " + String(r_spd) + "\trref: " + String(r_ref) + "\trvolt: " + String(r_volt) +
                    "\t\tx: " + String(x) + "\ty: " + String(y) + "\txG: " + String(xG) + "\tyG: " + String(yG);
      LogInfo(info);
      updated = false;

    }
    done = false;
  }
  if (A7_STREAM.available() > 0) {    // receive input from the A7 module (Serial1)
    String msg = "";
    if(waiting){
      get_A7_resp();  // read the message (function in A7.h)
      msg = resp;     // save the message (variable in A7.h)
      resp = "";
    }
    else{
      msg = readStr();
    }
    if (msg.length() > 2)   // process the received message
    {
      if (msg.substring(0, 2).equals("xy")) {
        readXYG(msg);
        resp = "";
      }
      else if(msg.equals("stop")){
        xG = x;
        yG = y;

        resp = "";
      }
      else if(msg.equals("+TCPCLOSE:0")){
        disconnected();
      }
    }
  }

}
inline void arbiter(){
  fbbc.arbiter();
  newvolt = true;
  vw2lr();  // convert v and w to left speed and right speed
}
inline void cntrISR() // ISR that runs every 210 milliseconds (for speed control)
{
  // compute the speed of the car
  read_rm();
  read_lm();
  ctr2lr();   // convert counter values to centimeter/second
  if (newvolt){
    spd2volt_init();
    newvolt = false;
  }
  else
    spd2volt();
  // update motor values
  analogWrite(L_PWM_PIN, l_volt);
  analogWrite(R_PWM_PIN, r_volt);

  updatePos();
}

inline void updatePos()   // compute new position (using differential drive kinematic equations)
{
  lr2xyphi();
}

inline void readXYG(String cmd) // get the new goal coordinates
{
  int sp1 = cmd.indexOf(' ');
  int sp2 = cmd.indexOf(' ', sp1 + 1);
  xG = (double)cmd.substring(sp1 + 1, sp2).toInt();
  yG = (double)cmd.substring(sp2 + 1, cmd.indexOf('~',sp2+1)).toInt();
}

the motor initialization code:
inline void setup_cntr()
{
  pinMode(CTR0_PIN, INPUT_PULLUP);
  pinMode(CTR5_PIN, INPUT_PULLUP);
  TCNT5H = 0;
  TCNT5L = 0;
  TCCR5B = 0X07;
  TCNT0 = 0;
  TCCR0B = 0X07;
}

inline void initMotors(){
  pinMode(L_FWD_PIN, OUTPUT);
  pinMode(L_BACK_PIN, OUTPUT);
  pinMode(L_PWM_PIN, OUTPUT);
  pinMode(L_EN_PIN, OUTPUT);
  digitalWrite(L_EN_PIN, HIGH);
  digitalWrite(L_FWD_PIN, HIGH);
  digitalWrite(L_BACK_PIN, LOW);

  pinMode(R_FWD_PIN, OUTPUT);
  pinMode(R_BACK_PIN, OUTPUT);
  pinMode(R_PWM_PIN, OUTPUT);
  pinMode(R_EN_PIN, OUTPUT);
  digitalWrite(R_EN_PIN, HIGH);
  digitalWrite(R_FWD_PIN, HIGH);
  digitalWrite(R_BACK_PIN, LOW);
}

ultrasonic sensors code:
#include "M_Ultrasonics.h"

M_Ultrasonics HCRS04;
void measISR();
void trigISR();
M_Ultrasonics::M_Ultrasonics()
{
  pinIndex = -1;
  for(int i=0; i < NUM_US; i++)
  {
    pinMode(trigs[i],OUTPUT); // trigs: array containing the trigger pins of the ultrasonic sensors
    digitalWrite(trigs[i],LOW);
  }
}
void M_Ultrasonics::begin(uint32_t period, volatile double *dists_, volatile uint8_t *done_)
{
  Timer1.initialize(period*1000);
  Timer1.attachInterrupt(trigISR);
  dists = dists_;
  done = done_;
  pinIndex = -1;
  for(int i=0; i < NUM_US; i++)
  {
    pinMode(trigs[i],OUTPUT);
    digitalWrite(trigs[i],LOW);
    dists[i] = MAX_DIST;
  }
  enable_pci();
}
void M_Ultrasonics::end()
{
  Timer1.stop();
  Timer1.detachInterrupt();
  PCICR = 0;
}
inline void M_Ultrasonics::trig() // send the trigger signal to the sensor
{
  pinIndex ++;
  if(pinIndex == NUM_US)
  {
    pinIndex = 0;
    *done = 1;
  }
  set_pci();
  digitalWrite(trigs[pinIndex], HIGH);
  delayMicroseconds(ping);
  digitalWrite(trigs[pinIndex], LOW);
}
inline void M_Ultrasonics::enable_pci() // enable pin change interrupts on PORTK
{
  PCICR = 0x04;
}
inline void M_Ultrasonics::set_pci()  // activate interrupts for the current pin
{
  PCMSK2 = (1<<pinIndex);
}
inline unsigned long M_Ultrasonics::read_time() // convert the timer value to microseconds
{
  return (/*(TCNT1H<<8) | */TCNT1L) * F_CLOCK;
}
inline void M_Ultrasonics::meas()
{
  if(PINK & (1<<pinIndex)) {  // check if the pin is high
    s_echo = /*micros();/*/read_time();
    dists[pinIndex] = MAX_DIST*DOBST_COEFF;
  }
  else
  {
    f_echo =/* micros();/*/read_time();
//    d = (f_echo-s_echo)*soundSpeed/2E4;
    if(d < MAX_DIST) {
      dists[pinIndex] = d/**DOBST_COEFF*/;
    }
//    dists[pinIndex] = d; // (double)(f_echo - s_echo);
  }
}
ISR (PCINT2_vect) // handle pin change interrupt for A8 to A14 here
{
  measISR();
}
void measISR() // ISR called on rising or falling edge on the current pin
{
  HCRS04.meas();
}
void trigISR()  // function called every 30 millisecond to trigger the next ultrasonic sensor
{
  HCRS04.trig();
}

Many libraries expect delay(), millis() or micros() to work.

@EdgarBonet In that case I think I better leave it unused. thanks.

Many libraries expect delay(), millis() or micros() to work.

I copied Edgar Bonet's comment here to make a real answer, because Stack Exchange throws up old questions with no answers in the hope that someone will answer them. This is why you answer as an answer and not as a comment.

Half the time I make an answer somebody says it should have been a comment.  I'm starting to think that there's not a "right" way to use this site that won't be complained about by someone.

@Delta_G The policy is clearly stated in the [help], that is the definite reference how to do it, not what random people say. Answers are answers, comment are just comments.

OP states in the question that they don't use any libraries which would use these functions. so this answer was already in the question. that is why this was only a comment.

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


text:
Sending PUBX commands to GPS Board (Ublox NEO-6M) through SoftwareSerial
I am having trouble parsing NMEA sentences coming from a GY-NEO6MV2 board (https://www.cytron.io/p-gps-neo6mv2), using the TinyGPS (https://github.com/mikalhart/TinyGPS) library. The GPS board itself is connected to an Arduino Pro Mini 3v3 8MHz (ATmega328).
First of all, to start debugging I want to disable all NMEA sentences other than GGA and RMC (which are the only ones I need for this project).
According to the manual, this can be done by sending PUBX commands through the SoftwareSerial (no need for binary UBX).
I am doing this in the following way:
    #include <SoftwareSerial.h>
    #include <TinyGPS.h>

    // GPS SoftwareSerial
    // Shares pins with (MISO 12/ MOSI 11) used for SPI

    #define GPS_RX_PIN 12
    #define GPS_TX_PIN 11

    TinyGPS gps;
    SoftwareSerial GPSSerial(GPS_RX_PIN, GPS_TX_PIN);

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

          GPSSerial.print("$PUBX,40,GLL,0,0,0,0*5C\r\n");
          GPSSerial.print("$PUBX,40,ZDA,0,0,0,0*44\r\n");
          GPSSerial.print("$PUBX,40,VTG,0,0,0,0*5E\r\n");
          GPSSerial.print("$PUBX,40,GSV,0,0,0,0*59\r\n");
          GPSSerial.print("$PUBX,40,GSA,0,0,0,0*4E\r\n");
    }

    void loop()
    {
    // ...
    }

However, the GPS board will not respond to these commands and keep sending all the NMEA sentences.
FWIW, this is the original code I'm building my project on - https://github.com/billygr/arduino-aprs-tracker/blob/master/arduino-aprs-tracker.ino
Any thoughts would be appreciated.

I've tried your code sending those PUBX commands to a ublox module and they work successfully for me.
There are a lot of fakes about on the internet using AT6558 chips repackaged as ublox. Check the GPTXT messages that are output when the GPS module is powered up to see if its really a ublox module or a fake one like this:
$GPTXT,01,01,02,MA=CASIC*27
$GPTXT,01,01,02,HW=ATGM332D,0080113573899*18
$GPTXT,01,01,02,IC=AT6558-5N-31-0C500000,J7M911C-B2-008827*50
$GPTXT,01,01,02,SW=URANUS4,V4.3.0.5*18

You have not enough Zeros in your command!
$PUBX,40,GLL,0,0,0,0,0,05C (CR)(LF)
$PUBX,40,GSA,0,0,0,0,0,04E (CR)(LF)
$PUBX,40,GGA,0,0,0,0,0,05A (CR)(LF)
$PUBX,40,GSV,0,0,0,0,0,059 (CR)(LF)
$PUBX,40,RMC,0,0,0,0,0,047 (CR)(LF)
$PUBX,40,VTG,0,0,0,0,0,05E (CR)(LF)
$PUBX,40,GRS,0,0,0,0,0,05D (CR)(LF)
$PUBX,40,GST,0,0,0,0,0,05B (CR)(LF)


text:
MPU6500 via SPI
I'm trying to communicate with an MPU6500 sensor via SPI as I need the fastest possible update rate. I have trouble finding an easy to understand sample code, or perhaps a lightweight library how to configure and initialize the sensor and read gyro / accelerometer data via SPI.
So far I started adapting the code and info found at:
https://playground.arduino.cc/Main/MPU-6050
I thought it would be fairly easy to use SPI instead of I2C "Wire", and adapt the configuration and registers based on the data sheet, but I realized there's too many possible pitfalls.
Any recommendations?

I retracted my close flag, I never tried this sensor, normally components are either for SPI or I2C (or another communication means), but not supporting both, so I am surprised you can even change from I2C to SPI.

Read the data sheet and SPI protocol is quite easy to implement!

Thanks Michel, yes it does definitely support both.

For anyone who has not yet figured this out, its very simple.
Basically, for SPI communication with the sensor MPU 6500, its a bit different from what I2C has to offer.
In I2C, basically you will find the data packet is as follows:
(7 bit Slave Address + Read/Write Bit), but in SPI it is as follows:
(Read/Write Bit + 7 Bit Register Address), notice we dont even need the slave address in SPI as the Chip Select is connected from processor(Master) to Sensor(Slave).
So for SPI, lets say you want to write a value 64 to register 0x6B, then:
Transmission_data[2];
Transmission_data[0] = 0x6B;
Transmission_data[1] = 64;
Lets say you want to read a value from register 0x43, which is GYRO_X_High Byte value, then,
Transmission_data[1];
Transmission_data[0] = 0x43 | 0x80; // you need to or it with 0x80(decimal = 128)
Thanks...Hope this helps someone in need of help for SPI as I struggled too in finding this information.


text:
DS3231 with Arduino Nano for Timing precision
I need to synchronize two separate circuit boards working with Arduino Nano. The need is to activate one relay using Arduino-1 after 45 minutes, and another relay using Arduino-2 after 45.36 seconds. The time starts from the point of reception of input from an external switch common to both.
With ref to This question, and from the advice of edgar-bonet I have used one temperature-compensated RTC for timing the Arduinos externally (DS3231). I am using it's 32kHz pin from the chip for counting the ticks and in the Arduino using the interrupt to count the ticks.
The program is shown below.
float _sec = 1;

float secTime =  _sec * 1000UL; // second->millis
uint32_t coilTime = 5 * 1000UL; // second->millis

volatile uint32_t count = 0;
/*
 * 32768 ticks in 1 sec
 * 0.032768 tick in 1 us
 */

float _multiplier = 0.032768; // 32768 Hz

uint32_t _delay = secTime * _multiplier * 1000UL ;

volatile bool onFlag = false;

ISR(INT1_vect, ISR_NOBLOCK) {
  count = count + 1UL;
  if (_delay == count) {
    PORTC |= (1 << 5);
    onFlag = true;
    EIMSK = 0;
  }
}

ISR(INT0_vect) {
  /* INTERRUPT re-initalization */
  EIMSK = 0;
  EICRA = B00001100; // INT0 - clear ; INT1 -  set
  EIFR  = 0;
  PORTB ^=  (1 << 0) | (1 << 1); // setting Green off and red on
  count = 0;
  EIMSK = B00000010; // INT0 - inactive ; INT1 - active
}

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

  /* PIN initialization */
  DDRB |= (1 << 0) | (1 << 1); // red led and green led

  pinMode(3, INPUT_PULLUP); // timer unit
  pinMode(2, INPUT); // interrupt unit

  DDRC |= (1 << 3) | (1 << 4) | (1 << 5); // relay, OUT_1, OUT_2

  /* LEDs state update */
  PORTB &=  ~(1 << 1); // red off.
  PORTB |= (1 << 0); // green on.

  PORTC &= ~(1 << 3); // A3-off

  /* INTERRUPT initalization */
  EICRA = B00000011; // INT0 - set ; INT1 - not set
  EIMSK = B00000001; // INT0 - active ; INT1 - inactive
  EIFR  = 0;
}

void loop() {

  if (onFlag) {

    PORTB |= (1 << 0); // setting green on

    delay(500);
    PORTC ^= (1 << 5);
    //    PORTB ^= (1 << 0) | (1 << 1);
    PORTB ^= (1 << 1); // setting red off
    while (true) {
      TCCR2B = 0;
      count = 0;
      PORTB ^= (1 << 0);
      delay(500);
    }
  }
}

When running the program, the result I am expecting is the accuracy of microseconds but for:

input -> Measured value
1 sec -> 1.000387792
2 sec -> 2.000784208
50 sec -> 50.020926833
250 sec -> 250.104557792

How do I make the clock more precise? In the data sheet it is said that the clock is accurate to +- 2ppm.
datasheet-ds3231

I'm not completely sure I understand your use case because, at least for the initial synchronisation, there is a connection between the 2 devices.
volatile uint32_t count . . . count = 0; beware of asynchronous non-atomic operations on multi-byte variables on an 8bit MCU. For high precision calculations, float may have limitations: float _multiplier = 0.032768; 2ppm is about one second every five days.

Can you please advise me on the correct variables to be used? In the initial case, I have a common switch connected to my devices and I use that as the interrupt signal.

1.0000000 / (1.000387792 / 32768 ) = 32755.29776 .... that makes 32755 ticks in 1 second

after 45 min and another relay using Arduino-2 after 45.36 seconds does not declare the necessary precision ... for example, 45.36 can be anywhere between 44.355000... and 45.364999...

@jsotola, If i am okay with that much dispersion what modifications to be done.?

Instead of using floats to specify the time interval,  why not  specify say 1 second as 32768? At a quick glance, the loss of ticks (in comparison to your reference) seems linear at around 13 per second. Maybe try switching off timer 0 to inhibit its possibly clashing interrupts and then you'll have to find another solution for delay().

I cannot understand what your code is trying to do, and I do not see how the code relates to the “input -> measured value” part of the question. I suggest you follow the advice in How to create a Minimal, Reproducible Example. 2. You have a very contrived way of writing _delay = 32768. Please, note that 0.032768 cannot be represented as a float, and will be rounded to the nearest representable number, which is 0.0327679999172687530517578125

This may not be a proper answer to your question. Instead of telling you
how to improve the accuracy, I will show you how to measure it. The
issue is that the code you posted is doing too much stuff, and it is not
clear how it could be measuring the clock accuracy. So, instead I
suggest you try the code below:

connect a push button between pin 2 and GND
connect the 32768 Hz signal to pin 5
watch the built-in LED blink

const uint8_t input_pin = 5;  // 32768 Hz on digital 5 = T1
const uint8_t clear_pin = 2;  // button to clear timer

void setup() {
    pinMode(input_pin, INPUT_PULLUP);
    pinMode(clear_pin, INPUT_PULLUP);
    pinMode(LED_BUILTIN, OUTPUT);

    // Configure Timer 1 as a counter.
    TCCR1A = 0;
    TCCR1B = _BV(CS11) | _BV(CS12);  // count falling edges of T1
}

void loop() {
    // Display bit 14 of the counter on the builtin LED.
    if (TCNT1 & (1 << 14)) {
        digitalWrite(LED_BUILTIN, HIGH);
    } else {
        digitalWrite(LED_BUILTIN, LOW);
    }

    // Clear the counter on button press.
    if (digitalRead(clear_pin) == LOW) {
        TCNT1 = 0;
    }
}

What this sketch does is use Timer/counter 1 as a counter in order to
count the falling edges of the 32768 Hz signal. Bit 14 of the counter
should then toggle at 1 Hz. This bit is output on the built-in LED to
let you check its frequency. You can use the push button to reset the
phase of the blinks.
If you have a very accurate clock at hand, you can use the push button
to synchronize the blinks with the ticks of that clock, and then see how
long it takes to get visibly out of phase. You can also synchronise the
blinks of two Arduinos and see for how long they stay in sync. If you
have a scope, you could measure a tiny offset between the edges of the
two Arduino's LEDs, then see how this offset evolves with time.

It looks like you have a drift problem (?) Some of the DS3231 RTC modules on the market have significantly more drift than the datasheet spec and the only way to know if you have one of those is to tune the aging register and test it. In a stable temperature environment you can usually get a -SN to a millisecond per day of clock drift.
This can be done with an Uno and a cheap GPS module: https://thecavepearlproject.org/2024/10/22/setting-accurate-rtc-time-with-a-gps-the-ds3231-aging-offset-to-reduce-drift/


text:
Moving and Stopping Stepping motor without using delay
I'm using a stepper motor with an external limit switch (so when power is on the motor will know where to start from) with an L6470 motor drive.
What I want to do here is

when power is ON → turn Clock Wise (CW) until it hits external Limit Switch
Once the limit switch is ON → Turn Anti-Clock Wise (CCW) for 550 mil seconds
Rest for 100 mil seconds
Turn Clock Wise (CW) for 200 mil seconds
Rest for 100 mil seconds
Turn Anti-Clock Wise (CCW) for 200 mil seconds
....loop from 3 to 6

My current code is using "counter". This is because I can't use "delay" in this code since it interrupts the limit switch activation code.
I've only written easy codes and don't know how to make it rest without using "delay".
Please help....
/***********************

回転

************************/
#include <Arduino.h>
#include <SPI.h>

/*************

long max_speed = 7000;// 70000 固定

long int dd = 200;// 微増・微減の量 400
int dt = 10; // 微増・微減にかける時間　ミリ秒

int t_interval = 10;// (休止する時間 みり秒）
int t_hold = 170; //　最高速を維持する時間　ミリ秒）

int steps;

#define PIN_SPI_MOSI 11
#define PIN_SPI_MISO 12
#define PIN_SPI_SCK 13
#define PIN_SPI_SS 10

#define PIN_L6470_SS PIN_SPI_SS

void L6470_write(unsigned char data);
void L6470_init(void);
void L6470_run(long speed);

long speed = 1000;
long int n_dir = 0 ;
long offTime;

int c_step = max_speed / dd;

const int limit_sw = 7;
bool switchState = false;
int counter = 0;
int milsec = 0;
bool speedSwitch = false;

void setup()
{
 pinMode(PIN_SPI_MOSI, OUTPUT);
 pinMode(PIN_SPI_MISO, INPUT);
 pinMode(PIN_SPI_SCK, OUTPUT);
 pinMode(PIN_L6470_SS, OUTPUT);

 pinMode(limit_sw, INPUT_PULLUP );

 digitalWrite(PIN_L6470_SS, HIGH);

 SPI.begin();

 Serial.begin(9600);

 L6470_init();

 Serial.println("Start...");

void loop()
{

int value = digitalRead(limit_sw);

if(value == 0){
  counter ++;
  if(counter > 50){//もともと３
    switchState = true;
    counter = 50;
  }
}
if (switchState == true){
  milsec++;
  Serial.println(milsec);
  if(milsec > 550){
    speedSwitch = !speedSwitch;
    milsec = 0;
  }

  int speed;
  if(speedSwitch == true){
    //Serial.println("speedSwitch : true");
    speed = 200;

  }

  else{
    //Serial.println("speedSwitch : false");
    speed = -200;
  }

}

else{

   L6470_run( 100 );//速度

}
}

void L6470_write(unsigned char data)
{
 // ~SSイネーブル。
 digitalWrite(PIN_L6470_SS, LOW);
 // SPI転送。
 SPI.transfer(data);
 // ~SSディスエーブル。
 digitalWrite(PIN_L6470_SS, HIGH);
}

void L6470_init()
{
 // MAX_SPEED設定。
 /// レジスタアドレス。
 L6470_write(0x07);
 // 最大回転スピード値(10bit)　００２０

 L6470_write(0x00);
 L6470_write(0x90);

 // KVAL_HOLD設定。
 /// レジスタアドレス。
 L6470_write(0x09);
 // モータ停止中の電圧設定(8bit)
 L6470_write(0xFF);

 // KVAL_RUN設定。
 /// レジスタアドレス。
 L6470_write(0x0A);
 // モータ定速回転中の電圧設定(8bit)
 //L6470_write(0xFF);
 L6470_write(0x64);

 // KVAL_ACC設定。
 /// レジスタアドレス。
 L6470_write(0x0B);
 // モータ加速中の電圧設定(8bit)
 L6470_write(0xFF);

 // KVAL_DEC設定。
 /// レジスタアドレス。
 L6470_write(0x0C);
 // モータ減速中の電圧設定(8bit)
 L6470_write(0xFF);

 // OCD_TH設定。
 /// レジスタアドレス。
 L6470_write(0x13);
 // オーバーカレントスレッショルド設定(4bit)
 L6470_write(0x0F);

 // STALL_TH設定。
 /// レジスタアドレス。
 L6470_write(0x14);
 // ストール電流スレッショルド設定(4bit)
 L6470_write(0x7F);
}

void L6470_run(long speed)
{
 unsigned short dir;
 unsigned long spd;
 unsigned char spd_h;
 unsigned char spd_m;
 unsigned char spd_l;

//spd = speed;

 // 方向検出。

 if (speed < 0)
 {
  dir = 0x50;
  spd = -1 * speed;
 }
 else
 {
  dir = 0x51;
  spd = speed;
 }

 // 送信バイトデータ生成。
 spd_h = (unsigned char)((0x0F0000 & spd) >> 16);
 spd_m = (unsigned char)((0x00FF00 & spd) >> 8);
 spd_l = (unsigned char)(0x00FF & spd);

 // コマンド（レジスタアドレス）送信。
 L6470_write(dir);
 // データ送信。
 L6470_write(spd_h);
 L6470_write(spd_m);
 L6470_write(spd_l);

  Serial.print( " current spd = ");
  Serial.println( spd );
}


text:
DS3218MG Servo - Not working with power supply
I'm trying to run my DS3218MG Servo Motor with an external power supply and my arduino nano.
I'm using the following code:
#include<Servo.h>
Servo Myservo;
int pos;
void setup()
{
Myservo.attach(3);
}

void loop()
{

for(pos=0;pos<=180;pos++){
Myservo.write(pos);
delay(15);
}
  delay(1000);

  for(pos=180;pos>=0;pos--){
Myservo.write(pos);
delay(15);
}
  delay(1000);

}
According to the datasheet the servo needs a DC 4.8-6.8 voltage. My first attempt was to only use the arduino and no external power supply. So did the following connections:

servo's ground to arduino's ground
servo's + to arduino's 5V
servo's data to arduino's GPIO pin 3

Using this connection works fine and the servo rotatates to the desired positions. However, because the arduino does not supply enough current, i bought a power supply with the following specs:

With that, i did the following connections:

connect the ground of the power supply to arduino's ground (and servo)
keep the data pin
connect + of power supply to servo's +

Unfortunately, the servo does not move with the external power supply. IMO, it should have the right voltage and also supply enough current (at least as much as the Arduino).
Do you see the problem?

How are you powering the Arduino in the new setup?

regular usb cable for powering arduino

I would set the external power supply to 5V (your photo shows 6V) and try to measure the voltage of the servo while the Arduino is attempting to move it. Your servo is a high current device, which is not really suitable for connecting to a breadboard.

but 6 V should be fine since the servo allows DC 4.8-6.8 shouldn't it? However, nothing happens with 5v either - also when i directly connect the power +  to the servo +  instead of using a breadboard. How do I measure voltage of servo while arduino is attempting to move it?

Except you're interfacing a 5V device to it, which might or might not cause problems when running the servo at 6V (probably not, but the servo works at 5V either way). Did you measure the voltage on the servo's pins when you're trying to move it?

how can i measure this? do you mean the voltage from the power supply?

I mean measure the supply voltage going into the servo, as close to the servo as possible, to see if the breadboard is causing an issue (bad contacts, high resistance).

but as I said before, I also tried to remove the breadboard and solder the connections directly i.e. solder the + of the power to + of the servo. Shouldn't it actually work with that?

@starcat,  regular  usb cable for  powering  arduino


text:
Servo noise during program flash on Arduino
I'm running serveral servos using a driver A4988 and external power supply. Everything works fine.
I've just noticed one issue that I can't explain.
As soon as I upload a new program version on my arduino uno, while the external power supply is one, the servo makes some strange noises. After the upload has finished, the noise disappears.
Without any further details, can you explain this behavior? Does the arduino set some Pins to HIGH during flashing?
Thanks!

It would depend on which Arduino and what bootloader it's running.  Generally MCUs have their pins in INPUT mode when they reset.  Sometimes the bootloader will leave some pins configured for a particular mode by the some the sketch runs.  E.g. the Leonardo seems to leave pin 13 set to OUTPUT mode.
You usually want devices connected to your Arduino to have stable signals when the Arduino MCU is in reset, or in the bootloader, so it makes sense to pull the signal pins, that will later be output from the Arduino sketch, to known levels.  So maybe pulling your servo driver enable signal to inactive (HIGH) is appropriate.
Looking at the A4988, it has an EN (enable) pin, which seems to be active low.  So putting a high(ish) value resistor, say 5k or 10k, on it to VDD/HIGH (to inactive) is probably the thing to do.  When the Arduino is not driving the enable line to its low (active) state, that is when it's in the bootloader or being held in reset, the A4988 should stop its activity.

Can you explain what you mean with "Pulling servo signal to ground" ?

First time through, I'd been thinking of a typical hobby servo.  I've changed the wording there to be correct (I think) for the A4988 driver.  The basic idea is the same, when the MCU is not strongly influencing the signal (any signal really, the driver enable signal in this case) a resistor can be used to weakly influence the pin to the default level.


text:
Arduino PC to RS232 not reading data
I am trying to read data from RS232 Shield with an Arduino Mega.
This is the schematic pin, TX is 3 and RX is 2.
Wiring:
PC > USB-RS232 cable > Arduino RS232 Shield.
Software to send/receive data:
Hercules Setup Utility
From Arduino, I can transmit data to RS232, the TX led blink and I got the value at PC.
From PC, I send the data, the RX led blink but nothing is showed in Arduino Monitor.
#include <SoftwareSerial.h>

SoftwareSerial mySerial(2, 3); // RX, TX

void setup() {
  // Open serial communications and wait for port to open:
  Serial.begin(9600);
  while (!Serial) {
    ; // wait for serial port to connect. Needed for native USB port only
  }

  Serial.println("Goodnight moon!");

  // set the data rate for the SoftwareSerial port
  mySerial.begin(9600);
  mySerial.println("Hello, world?");
}

void loop() { // run over and over
  if (mySerial.available()) {
    Serial.write(mySerial.read());
  }
  if (Serial.available()) {
    mySerial.write(Serial.read());
  }
}

I also tried to move RX and TX to Pin 15 and 14 but worked as the same as before.

What does the 'RS232 direction pin' do?  If its only working one way then that would be the first place I would look at.  Also do you have you SD Shield plugged in at the same time?

@CodeGorilla Sorry, it was direction to RS485. And no, SD Card.

You're going to need to clarify if you have RS232 as in the title or RS485 as in the code, and you're going to need to show the full system wiring.  When you say PC, do you mean the one connected to the RS232 or RS485 connector, or do you mean the one connected to the Arduino USB port?   On the end which is not the Arduino serial monitor, what are you using to send/receive data?

@ChrisStratton forget RS485, just deleted that code, I wont use RS485 for nothing. I am using Hercules setup utility.

Ok, but the question remains too incomplete to be answerable.

@ChrisStratton What info I should provide?

Everything needed to debug the signal from one end to the other. For example your board seems covered with switches and options.

@ChrisStratton The switches are set to RS232 and SoftSerial, the other options are for RS485.

Found the problem, cant use PIN 2 as RX.

Note: Not all pins on the Mega and Mega 2560 support change
  interrupts, so only the following can be used for RX: 10, 11, 12, 13,
  50, 51, 52, 53, 62, 63, 64, 65, 66, 67, 68, 69

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


text:
Seeeduino XIAO write and read PWM duration (period) using timers
I am trying to communicate between two Seeeduino XIAO (chip: ATSAMD21G18A-MU) by way of TCC capture using register timers.
Square wave pulse duration varies from 200ns to 4us.
I found these two code samples, and I am now trying to change them up to make them work the way I intend to read and write these short pulses.

1) XIAO writing square wave (generate output)
This code works, but it is changing the pulse width and not the pulse period. Output is on pin D2 and D3. How can I make it change the polse period instead of the polse width?  Source
// Output 300kHz dual slope PWM on TCC0 with complementary outputs and dead time insertion
void setup()
{
  GCLK->CLKCTRL.reg = GCLK_CLKCTRL_CLKEN |        // Enable GCLK0
                      GCLK_CLKCTRL_GEN_GCLK0 |    // Select GCLK0 at 48MHz
                      GCLK_CLKCTRL_ID_TCC0_TCC1;  // Route GCLK0 to TCC0 and TCC1

  PORT->Group[PORTA].PINCFG[10].bit.PMUXEN = 1;   // Enable the port multiplexer for port pins PA10 and PA11
  PORT->Group[PORTA].PINCFG[11].bit.PMUXEN = 1;

  // Select the port pin multiplexer switch to option F for TCC0/WO[2] and TCC0/WO[3] on
  // port pins PA10 and PA11 respectively
  PORT->Group[PORTA].PMUX[10 >> 1].reg = PORT_PMUX_PMUXO_F | PORT_PMUX_PMUXE_F;

  TCC0->WAVE.reg = TCC_WAVE_POL2 |                // Reverse the signal polarity on channel 2
                   TCC_WAVE_WAVEGEN_DSBOTTOM;     // Dual slope PWM on TCC0
  while (TCC0->SYNCBUSY.bit.WAVE);                // Wait for synchronization

  //  48,000,000 / 300,000 = 160
  TCC0->PER.reg = 79;                             // Set the frequency of the PWM on TCC0 to 300kHz
  while(TCC0->SYNCBUSY.bit.PER);                  // Wait for synchronization

  TCC0->CC[2].reg = 40;                           // Output a 50% duty-cycle
  while(TCC0->SYNCBUSY.bit.CC2);                  // Wait for synchronization

  TCC0->CC[3].reg = 35;                           // Output a 43% duty-cycle
  while(TCC0->SYNCBUSY.bit.CC3);                  // Wait for synchronization

  TCC0->CTRLA.bit.ENABLE = 1;                     // Enable TCC0
  while (TCC0->SYNCBUSY.bit.ENABLE);              // Wait for synchronization
}

void loop(){
  TCC0->CTRLBSET.reg = TCC_CTRLBSET_LUPD;         // Set the Lock Update (LUPD) bit
  while (TCC0->SYNCBUSY.bit.CTRLB);               // Wait for synchroniztion
  TCC0->CCB[2].reg = 40;                          // Output a 50% duty-cycle
  while(TCC0->SYNCBUSY.bit.CCB2);                 // Wait for synchronization
  TCC0->CCB[3].reg = 35;                          // Output a 43% duty-cycle
  while(TCC0->SYNCBUSY.bit.CCB3);                 // Wait for synchronization
  TCC0->CTRLBCLR.reg = TCC_CTRLBCLR_LUPD;         // Clear the Lock Update (LUPD) bit
  while (TCC0->SYNCBUSY.bit.CTRLB);               // Wait for synchroniztion
  delay(1000);                                    // Wait for 1 second

  TCC0->CTRLBSET.reg = TCC_CTRLBSET_LUPD;         // Set the Lock Update (LUPD) bit
  while (TCC0->SYNCBUSY.bit.CTRLB);               // Wait for synchroniztion
  TCC0->CCB[2].reg = 20;                          // Output a 25% duty-cycle
  while(TCC0->SYNCBUSY.bit.CCB2);                 // Wait for synchronization
  TCC0->CCB[3].reg = 15;                          // Output a 18% duty-cycle
  while(TCC0->SYNCBUSY.bit.CCB3);                 // Wait for synchronization
  TCC0->CTRLBCLR.reg = TCC_CTRLBCLR_LUPD;         // Clear the Lock Update (LUPD) bit
  while (TCC0->SYNCBUSY.bit.CTRLB);               // Wait for synchroniztion
  delay(1000);
}

2) XIAO reading square wave (input capture); Period and Pulse-Width (PPW) Capture
This code works, but it reads the frequency over a period of 1 second, and not just the duration of a polse period. Input is on D6. How can I make these changes to the code for it to work?  Source
// Count the number of pulses on pin D6 (PB08) over a 1 second period
void setup()
{
  SerialUSB.begin(115200);                  // Initialise the native serial port
  while(!SerialUSB);                        // Wait for the console to open

  PM->APBCMASK.reg |= PM_APBCMASK_EVSYS;    // Switch on the event system peripheral

  ////////////////////////////////////////////////////////////////////////////////////////
  // Generic Clock Initialisation

  GCLK->GENDIV.reg =  GCLK_GENDIV_DIV(1) |          // Select clock divisor to 1
                      GCLK_GENDIV_ID(4);            // Select GLCK4

  GCLK->GENCTRL.reg = GCLK_GENCTRL_IDC |            // Set the duty cycle to 50/50 HIGH/LOW
                      GCLK_GENCTRL_GENEN |          // Enable GCLK
                      GCLK_GENCTRL_SRC_XOSC32K |    // Select GCLK source as
                                                    //    external 32.768kHz crystal (XOSC32K)
                      GCLK_GENCTRL_ID(4);           // Select GCLK4
  while (GCLK->STATUS.bit.SYNCBUSY);                // Wait for synchronization

  GCLK->CLKCTRL.reg = GCLK_CLKCTRL_CLKEN |          // Enable generic clock
                      GCLK_CLKCTRL_GEN_GCLK0 |      // GCLK0 at 48MHz
                      GCLK_CLKCTRL_ID_TCC0_TCC1;    // As a clock source for TCC0 and TCC1

  GCLK->CLKCTRL.reg = GCLK_CLKCTRL_CLKEN |          // Enable generic clock
                      GCLK_CLKCTRL_GEN_GCLK4 |      // GCLK4 at 32.768kHz
                      GCLK_CLKCTRL_ID_TCC2_TC3;     // As a clock source for TCC2 and TC3

  //////////////////////////////////////////////////////////////////////////////////////////////
  // TCC2 Initialisation - reference timer: measures a 1s period

  TCC2->PER.reg = 32767;                             // Set the period (PER) register for a
                                                     // PWM period of 1s
  while (TCC2->SYNCBUSY.bit.PER);                    // Wait for synchronization

  TCC2->WAVE.reg = TCC_WAVE_WAVEGEN_NPWM;            // Set timer to Normal PWM mode (NPWM)
  while (TCC2->SYNCBUSY.bit.WAVE);                   // Wait for synchronization

  TCC2->CTRLBSET.reg = TCC_CTRLBSET_ONESHOT;         // Enable oneshot operation
  while(TCC2->SYNCBUSY.bit.CTRLB);                   // Wait for synchronization

  NVIC_SetPriority(TCC2_IRQn, 0);    // Set the Nested Vector Interrupt Controller
                                     //   (NVIC) priority for TCC2 to 0 (highest)
  NVIC_EnableIRQ(TCC2_IRQn);         // Connect TCC2 to Nested Vector Interrupt
                                     //   Controller (NVIC)

  TCC2->INTENSET.reg = TCC_INTENSET_OVF;   // Enable overflow (OVF) interrupts on TCC2

  TCC2->CTRLA.bit.ENABLE = 1;              // Enable TCC2
  while (TCC2->SYNCBUSY.bit.ENABLE);       // Wait for synchronization

  ////////////////////////////////////////////////////////////////////////////////////////
  // TCC0 Initialisation - measurement counter: counts the number of incoming of pulses

  PORT->Group[PORTB].PINCFG[8].bit.PMUXEN = 1;               // Enable the port multiplexer
                                                             //   on port pin PB08 (D6)
  PORT->Group[PORTB].PMUX[8 >> 1].reg |= PORT_PMUX_PMUXE_A;  // Set-up PB08 (D6) as an
                                                             //   EIC (interrupt)

  EIC->EVCTRL.reg |= EIC_EVCTRL_EXTINTEO8;       // Enable event output on external interrupt 8
  EIC->CONFIG[1].reg |= EIC_CONFIG_SENSE0_HIGH;  // Set interrupt to detect a HIGH level
  EIC->INTENCLR.reg = EIC_INTENCLR_EXTINT8;      // Clear the interrupt flag on channel 8
  EIC->CTRL.bit.ENABLE = 1;                      // Enable EIC peripheral
  while (EIC->STATUS.bit.SYNCBUSY);              // Wait for synchronization

  EVSYS->USER.reg = EVSYS_USER_CHANNEL(1) |      // Attach the event user (receiver) to
                                                 //   channel 0 (n + 1)
                    EVSYS_USER_USER(EVSYS_ID_USER_TCC0_EV_0);  // Set the event user (receiver)
                                                               //   as timer TCC0, event 0

  EVSYS->CHANNEL.reg = EVSYS_CHANNEL_EDGSEL_NO_EVT_OUTPUT |    // No event edge detection
                       EVSYS_CHANNEL_PATH_ASYNCHRONOUS |       // Set event path as asynchronous
                       EVSYS_CHANNEL_EVGEN(EVSYS_ID_GEN_EIC_EXTINT_8) |  // Set event generator
                       //   (sender) as external interrupt 8
                       EVSYS_CHANNEL_CHANNEL(0);               // Attach the generator (sender)
                                                               //   to channel 0

  TCC0->EVCTRL.reg = TCC_EVCTRL_TCEI0 |       // Enable TCC0 event 0 inputs
                     TCC_EVCTRL_EVACT0_INC;   // Increment the TCC0 counter on receiving an event 0

  TCC0->CTRLA.bit.ENABLE = 1;          // Enable TCC0
  while (TCC0->SYNCBUSY.bit.ENABLE);   // Wait for synchronization
}

void loop()
{
  startConversion();     // Start a conversion over the 1 second integration window
  delay(3500);           // Wait for 1 second
}

void startConversion()
{
  TCC2->CTRLBSET.reg = TCC_CTRLBSET_CMD_RETRIGGER;   // Retrigger the timer TCC2 to
                                                     //   start the integration window
  while (TCC2->SYNCBUSY.bit.CTRLB);                  // Wait for synchronization
  TCC0->CTRLBSET.reg = TCC_CTRLBSET_CMD_RETRIGGER;   // Retrigger the timer TCC0 to
                                                     //   start the count
  while (TCC0->SYNCBUSY.bit.CTRLB);                  // Wait for synchronization
}

void TCC2_Handler()
{
  TCC2->INTFLAG.bit.OVF = 1;                         // Clear the TCC2 overflow interrupt flag
  TCC0->CTRLBSET.reg = TCC_CTRLBSET_CMD_READSYNC;    // Trigger a read synchronization
                                                     //   on the COUNT register
  while (TCC0->SYNCBUSY.bit.CTRLB);                  // Wait for the CTRLB register write synchronization
  while (TCC0->SYNCBUSY.bit.COUNT);                  // Wait for the COUNT register read sychronization
  SerialUSB.println(TCC0->COUNT.reg);                // Print the result
}

Some helpful page explaining these timers
https://www.picotech.com/support/topic24051.html
https://shawnhymel.com/1710/arduino-zero-samd21-raw-pwm-using-cmsis/

1) Writing short square wave pulses to pin D3 using Seeeduino XIAO
Timer setup derived from this github post and includes update suggestion by MartinL.
void setup()  //TCC1 Timer-Setup AT-SAMD21-G18 ARM Cortex M0
{
  setupTimers();
  changePer(125);
}
void loop() {
  // testing
  changePer(20);
  delay(3000);
  for (byte i = 0; i < 15; i++) {
    changePer(40 + (i+1)*4);
    delay(1000);
  }
  delay(2000);
}

// Change Pulse Period
void changePer(uint16_t myPer) {
  TCC1->CTRLBSET.reg = TCC_CTRLBSET_LUPD;     // Set the Lock Update bit
  while (TCC1->SYNCBUSY.bit.CTRLB);           // Wait for synchronization
  TCC1->PERB.reg = myPer;                     // Set period
  while(TCC1->SYNCBUSY.bit.PERB);             // Wait for synchronization
  TCC1->CCB[1].reg = myPer/2;                 // Set duty-cycle to 50%
  while(TCC1->SYNCBUSY.bit.CCB0);             // Wait for synchronization
  TCC1->CTRLBCLR.reg = TCC_CTRLBCLR_LUPD;     // Clear the Lock Update bit
  while (TCC1->SYNCBUSY.bit.CTRLB);           // Wait for synchronization
}

// Output PWM on digital pin D3 using timer TCC1 (10-bit resolution)
void setupTimers() {
  REG_GCLK_GENDIV = GCLK_GENDIV_DIV(1) |        // Divide the 48MHz clock source by divisor N=1: 48MHz/1=48MHz
                    GCLK_GENDIV_ID(4);          // Select Generic Clock (GCLK) 4
  while (GCLK->STATUS.bit.SYNCBUSY) ;           // Wait for synchronization

  REG_GCLK_GENCTRL = GCLK_GENCTRL_IDC |         // Set the duty cycle to 50/50 HIGH/LOW
                     GCLK_GENCTRL_GENEN |       // Enable GCLK4
                     GCLK_GENCTRL_SRC_DFLL48M | // Set the 48MHz clock source
                     GCLK_GENCTRL_ID(4);        // Select GCLK4
  while (GCLK->STATUS.bit.SYNCBUSY) ;           // Wait for synchronization

  // Enable the port multiplexer for the digital pin D3 and D11  **** g_APinDescription() converts Arduino Pin to SAMD21 pin
  PORT->Group[g_APinDescription[3].ulPort].PINCFG[g_APinDescription[3].ulPin].bit.PMUXEN = 1;

  // Connect the TCC1 timer to digital output D3 - port pins are paired odd PMUO and even PMUXE
  // F & E specify the timers: TCC0, TCC1 and TCC2
  // D2 is on PA10 = even, use Device E for TCC1
  PORT->Group[g_APinDescription[2].ulPort].PMUX[g_APinDescription[2].ulPin >> 1].reg |= PORT_PMUX_PMUXO_E;

  // Feed GCLK4 to TCC0 and TCC1
  REG_GCLK_CLKCTRL = GCLK_CLKCTRL_CLKEN |       // Enable GCLK4 to TCC0 and TCC1
                     GCLK_CLKCTRL_GEN_GCLK4 |   // Select GCLK4
                     GCLK_CLKCTRL_ID_TCC0_TCC1; // Feed GCLK4 to TCC0 and TCC1
  while (GCLK->STATUS.bit.SYNCBUSY) ;           // Wait for synchronization

  // Dual slope PWM operation: timers countinuously count up to PER register value then down 0
  REG_TCC1_WAVE |= TCC_WAVE_POL(0xF) |          // Reverse the output polarity on all TCC0 outputs
                   TCC_WAVE_WAVEGEN_DSBOTH;     // Setup dual slope PWM on TCC0
  while (TCC1->SYNCBUSY.bit.WAVE) ;             // Wait for synchronization

  // Each timer counts up to a maximum or TOP value set by the PER register,
  // this determines the frequency of the PWM operation: Freq = 48Mhz/(2*N*PER)
  REG_TCC1_PER = 256;               // Set the FreqTcc of the PWM on TCC1 to 24Khz
  while (TCC1->SYNCBUSY.bit.PER) ;  // Wait for synchronization

  // Divide the GCLOCK signal by 1 giving  in this case 48MHz (20.83ns) TCC1 timer tick and enable the outputs
  REG_TCC1_CTRLA |= TCC_CTRLA_PRESCALER_DIV1 | // Divide GCLK4 by 1
                    TCC_CTRLA_ENABLE;          // Enable the TCC0 output
  while (TCC1->SYNCBUSY.bit.ENABLE) ; // Wait for synchronization
}

2) Reading short square waves with Seeeduino XIAO pin D2
It is thanks to MartinL that I got this to work. Source
// Setup TC4 to capture pulse-width and period on digital pin D2 on Seeeduino Xiao
volatile boolean periodComplete;
volatile uint32_t isrPeriod;
volatile uint32_t isrPulsewidth;
uint32_t period;
uint32_t pulsewidth;

void setup()   {
  SerialUSB.begin(115200);                         // Initialise the native serial port
  while(!SerialUSB);                               // Wait for the console to open

  PM->APBCMASK.reg |= PM_APBCMASK_EVSYS;           // Switch on the event system peripheral

  GCLK->GENDIV.reg = GCLK_GENDIV_DIV(1) |          // Divide the 48MHz system clock by 1 = 48MHz
                     GCLK_GENDIV_ID(4);            // Set division on Generic Clock Generator (GCLK) 4

  GCLK->GENCTRL.reg = GCLK_GENCTRL_IDC |           // Set the duty cycle to 50/50 HIGH/LOW
                      GCLK_GENCTRL_GENEN |         // Enable GCLK 4
                      GCLK_GENCTRL_SRC_DFLL48M |   // Set the clock source to 48MHz
                      GCLK_GENCTRL_ID(4);          // Set clock source on GCLK 4
  while (GCLK->STATUS.bit.SYNCBUSY);               // Wait for synchronization

  GCLK->CLKCTRL.reg = GCLK_CLKCTRL_CLKEN |         // Route GCLK4 to TC4 and TC5
                      GCLK_CLKCTRL_GEN_GCLK4 |
                      GCLK_CLKCTRL_ID_TC4_TC5;

  // Enable the port multiplexer on port pin PA10
  PORT->Group[PORTA].PINCFG[10].bit.PMUXEN = 1;
  // Set-up the pin as an EIC (interrupt) on port pin PA10
  PORT->Group[PORTA].PMUX[10 >> 1].reg |= PORT_PMUX_PMUXE_A;

  EIC->EVCTRL.reg |= EIC_EVCTRL_EXTINTEO10;                                // Enable event output on external interrupt 10
  EIC->CONFIG[1].reg |= EIC_CONFIG_SENSE2_HIGH;                            // Set event detecting a HIGH level
  EIC->INTENCLR.reg = EIC_INTENCLR_EXTINT10;                               // Disable interrupts on external interrupt 10
  EIC->CTRL.reg |= EIC_CTRL_ENABLE;                                        // Enable EIC peripheral
  while (EIC->STATUS.bit.SYNCBUSY);                                        // Wait for synchronization

  EVSYS->USER.reg = EVSYS_USER_CHANNEL(1) |                                // Attach the event user (receiver) to channel 0 (n + 1)
                    EVSYS_USER_USER(EVSYS_ID_USER_TC4_EVU);                // Set the event user (receiver) as timer TC4

  EVSYS->CHANNEL.reg = EVSYS_CHANNEL_EDGSEL_NO_EVT_OUTPUT |                // No event edge detection
                       EVSYS_CHANNEL_PATH_ASYNCHRONOUS |                   // Set event path as asynchronous
                       EVSYS_CHANNEL_EVGEN(EVSYS_ID_GEN_EIC_EXTINT_10) |   // Set event generator (sender) as external interrupt 10
                       EVSYS_CHANNEL_CHANNEL(0);                           // Attach the generator (sender) to channel 0

  TC4->COUNT32.EVCTRL.reg = TC_EVCTRL_TCEI |               // Enable the TC event input
                            //TC_EVCTRL_TCINV |              // Invert the event input
                            TC_EVCTRL_EVACT_PPW;           // Set up the timer for capture: CC0 period, CC1 pulsewidth

  TC4->COUNT32.CTRLC.reg = TC_CTRLC_CPTEN1 |               // Enable capture on CC1
                           TC_CTRLC_CPTEN0;                // Enable capture on CC0
  while (TC4->COUNT32.STATUS.bit.SYNCBUSY);                // Wait for synchronization

  NVIC_SetPriority(TC4_IRQn, 0);      // Set the Nested Vector Interrupt Controller (NVIC) priority for TC4 to 0 (highest)
  NVIC_EnableIRQ(TC4_IRQn);           // Connect the TC4 timer to the Nested Vector Interrupt Controller (NVIC)

  TC4->COUNT32.INTENSET.reg = TC_INTENSET_MC1 |            // Enable compare channel 1 (CC1) interrupts
                              TC_INTENSET_MC0;             // Enable compare channel 0 (CC0) interrupts

  TC4->COUNT32.CTRLA.reg = //TC_CTRLA_PRESCSYNC_PRESC |      // Overflow on precaler clock, (rather than the GCLK)
                           TC_CTRLA_PRESCALER_DIV1  |      // Set prescaler to 1, 48MHz/1 = 48MHz
                           TC_CTRLA_MODE_COUNT32;          // Set TC4/TC5 to 32-bit timer mode

  TC4->COUNT32.CTRLA.bit.ENABLE = 1;                       // Enable TC4
  while (TC4->COUNT32.STATUS.bit.SYNCBUSY);                // Wait for synchronization
}

void loop() {
  if (periodComplete)                             // Check if the period is complete
  {
    noInterrupts();                               // Read the new period and pulse-width
    period = isrPeriod;
    pulsewidth = isrPulsewidth;
    interrupts();
    SerialUSB.print("PW: ");
    SerialUSB.print(pulsewidth);
    SerialUSB.print(F("   "));
    SerialUSB.print("P: ");
    SerialUSB.println(period);
    periodComplete = false;                       // Start a new period
  }
}

void TC4_Handler()                                // Interrupt Service Routine (ISR) for timer TC4
{
  // Check for match counter 0 (MC0) interrupt
  if (TC4->COUNT32.INTFLAG.bit.MC0)
  {
    TC4->COUNT32.READREQ.reg = TC_READREQ_RREQ |           // Enable a read request
                               TC_READREQ_ADDR(0x18);      // Offset address of the CC0 register
    while (TC4->COUNT32.STATUS.bit.SYNCBUSY);              // Wait for (read) synchronization
    isrPeriod = TC4->COUNT32.CC[0].reg;                    // Copy the period
    periodComplete = true;                                 // Indicate that the period is complete
  }

  // Check for match counter 1 (MC1) interrupt
  if (TC4->COUNT32.INTFLAG.bit.MC1)
  {
    TC4->COUNT32.READREQ.reg = TC_READREQ_RREQ |           // Enable a read request
                               TC_READREQ_ADDR(0x1A);      // Offset address of the CC1 register
    while (TC4->COUNT32.STATUS.bit.SYNCBUSY);              // Wait for (read) synchronization
    isrPulsewidth = TC4->COUNT32.CC[1].reg;                // Copy the pulse-width
  }
}


text:
Why are characters with value above 127 "padded" with 1s to be 16 bits long, while ones with values 0-127 aren't?
I am using the Arduino IDE to run and monitor, with an Arduino Nano clone.
This code shows what I mean by the question:
char foo = 127;
char bar = 128;
Serial.println(String(foo, BIN));
Serial.println(String(bar, BIN));
foo = 383;
bar = 384;
Serial.println(String(foo, BIN));
Serial.println(String(bar, BIN));

prints
1111111
1111111110000000
1111111
1111111110000000

It still happens if I then cast the elements to char, but not if I cast them to uint8_t:
char foo = 127;
char bar = 128;
Serial.println(String((char)foo, BIN));
Serial.println(String((char)bar, BIN));
Serial.println(String((uint8_t)foo, BIN));
Serial.println(String((uint8_t)bar, BIN));

1111111
1111111110000000
1111111
10000000

It behaves the same if I do some arithmetic as well:
char foo = 127;
char bar = 128;
Serial.println(String(foo / 64, BIN));
Serial.println(String(bar / 64, BIN));

1
1111111111111110

Why is this? If I assign a number bigger than 255, but smaller than 384, it behaves like for numbers below 128, but above that, it does it again, so it's obvious that only the least significant 8 bits of the value are stored as expected, but in cases where (n mod 255) > 127 (so the 8th bit is 1) they are retrieved from memory together with another 8 bits, which are all 1s.
I can live without an answer to the above issue, what I really need to have confirmed is the following:
If I were to store and retrieve a uint16_t as two elements of a char[], it would always be safe (and not undefined behavior) if I did it as follows, right?:
uint16_t foo = 34952;
char bar[2];
bar[0] = foo >> 8;
bar[1] = foo;
uint16_t extracted = (uint16_t((uint8_t)bar[0])) << 8 | (uint8_t)bar[1];

Thank you in advance for any help you can provide.

On the AVR platform the char type happens to be signed, and it can
store numbers in the range [−128, +127]. Thus, when you write
char bar = 128;

You are asking to store in bar a number that does not fit. It then
gets reduced modulo 28 into the value that does fit, namely
−128. For the kind of manipulations you are trying to make, I would
recommend you use uint8_t instead of char.

it would be always safe (and not undefined behavior) if I did it as
follows

It is indeed safe, and the casts you use are needed to make it safe.

"the char type happens to be signed" Oh, right! I forgot about that before, and I thought this was the key, but now I checked, and the results for -128 are exactly the same as for 128, it also doesn't help if I try casting it to char (either for storing or retrieving). "use uint8_t instead of char" great that you pointed that out, I shouldn't have been using char[] in the first place, but originally I was using a String and then moved over as that would terminate at the first NUL. It didn't occur to me to just use uint8_t[], but thankfully that still works with LoRa.

@Boba0514, 'Arduino language' has byte type too. it is a nicer name for uint8_t

@Juraj: “nicer” is subjective. Personally, the word “byte” evokes to me a unit of information storage equal to 8 bits, which could be used to store a signed number, an unsigned number, a collection of flags (that would have no meaningful interpretation as a number), or whatever one may want to put there. The name “uint8_t”, while not as nicely sounding, clearly states that it holds an unsigned integer. Note that Java has a byte data type, and it is signed.


text:
Program a mega2560 from a different Serial port
I want to be able to use my HC-05, currently on Serial3 to download code to on my 2560 from a connected android tablet. I'm currently running MegaCore, which has optiboot on it.
I've looked for examples of this and can't find one. Surely someone is doing this and the optiboot documentation says you can do it.
I am currently planning on downloading the hex file, but let me know if there's a better approach.
Thanks.

download from where over HC-05? what format? hex or bin? or you want to make a Serial upload with avrdude over HC-05 on Serial3? then you need the bootloader to listen at that Serial

@Juraj What format should I use? I was planning on bin, but what format to write to the flash? Download from a tablet in the field that has the internet connection. That's kind of what I'm asking. How do I get the bootloader to listen to Serial3?

you want to use InternalStorage of my ArduinoOTA library to store and apply the updated sketch binary?

@Juraj That would be great! Will that let me read from the Serial port?

the transport of the binary is on you. the only transport available in the library is receiving upload from the IDE. see the Advanced examples on how to use InternalStorage with alternative transport of the binary

@Juraj The example in ArduinoOTA?

yes, the examples in the Advanced section

@Juraj And I should be converting the hex file to bytes at two characters per byte, and then writing that directly to flash. Is that correct?

let the avr tools create the binary. https://github.com/jandrassy/ArduinoOTA/blob/master/extras/avr/platform.local.txt#L4

Let us continue this discussion in chat.

you could write an answer

@Juraj Don't really have one yet. I'm currently using OTA libraries.


text:
Code exceeds Uno board memory
I have been stuck for a long time on a piece of Arduino code that performs an FFT on a Photoplethysmogram signal and decides signal quality after that.
#include <math.h>
#include "arduinoFFT.h"
#include <EEPROM.h>

//N=10 pt moving average
//For bidmc data of first 10 patients, MA = 0.4613849
double baseline=0.4613849;
float lm=1.0; //amplitude threshold
float ref_voltage=1.0; //saturation reference voltage
float cutoff=4.0;
float fs=0.02;
float zero_amp=0.015;

float pi=3.14159265;  //Universal Constants
float e=2.71828;
const int flen=61;

#define SAMPLES 128           //Must be a power of 2
#define SAMPLING_FREQUENCY 50 //Hz, must be less than 10000 due to ADC

arduinoFFT FFT = arduinoFFT();
unsigned int sampling_period_us;
unsigned long microseconds;

double vReal[SAMPLES];
double vImag[SAMPLES];

void setup() {
  Serial.begin(9600);
  sampling_period_us = round(1000000*(1.0/SAMPLING_FREQUENCY));
}

void loop() {
  //float arr[]={0.43597,0.43206,0.42815,0.42424,0.42131,0.41838,0.4174,0.41642,0.41544,0.41447,0.41251,0.41153,0.40958,0.40762,0.40665,0.40665,0.40665,0.40762,0.4086,0.4086,0.41056,0.41153,0.41153,0.41056,0.4086,0.40665,0.40469,0.40469,0.40567,0.4086,0.41251,0.42033,0.43206,0.45259,0.4741,0.4956,0.51808,0.5347,0.55034,0.56403,0.57576,0.58456,0.59238,0.59629,0.59922,0.60117,0.60215,0.60313,0.60313,0.60117,0.59824,0.59335,0.58553,0.57771,0.57185,0.56207,0.54741,0.53372,0.52102,0.50929,0.50244,0.49756,0.4956,0.49462,0.49365,0.49365,0.49365,0.49169,0.48876,0.4868,0.48387,0.48094,0.47801,0.47507,0.47116,0.46823,0.46334,0.45846,0.45357,0.44868,0.44379,0.43891,0.435,0.43109,0.4262,0.42326,0.42033,0.41838,0.41642,0.41447,0.41447,0.41349,0.41251,0.41251,0.41251,0.41251,0.41251,0.41349,0.41544,0.4174,0.41935,0.42033,0.42131,0.42131,0.42033,0.41935,0.41642,0.41447,0.41349,0.41349,0.41642,0.42131,0.42815,0.43695,0.45064,0.46823,0.4868,0.50538,0.52395,0.54154,0.55816,0.57185,0.58162,0.58749,0.59042,0.59042,0.5914,0.59042,0.58944,0.58651,0.5826,0.57771,0.57087,0.56305,0.5523,0.54057,0.52884,0.51711,0.50733,0.49756,0.48778,0.47996,0.4741,0.47019,0.46823,0.46725,0.46628,0.46432,0.46041,0.4565};
  float arr[]={0.30303,0.29814,0.29326,0.28837,0.28446,0.28152,0.27859,0.27468,0.26979,0.26393,0.25806,0.25611,0.25904,0.27175,0.29521,0.32942,0.37341,0.42522,0.47116,0.51417,0.55914,0.6002,0.63539,0.66373,0.68622,0.70381,0.71652,0.72532,0.73118,0.73314,0.73314,0.73021,0.7263,0.72043,0.71359,0.70479,0.69501,0.68524,0.67351,0.6608,0.64614,0.6305,0.61388,0.59726,0.58065,0.56207,0.54252,0.52395,0.50538,0.48778,0.47312,0.46041,0.44868,0.43988,0.43304,0.42815,0.42522,0.42229,0.41935,0.4174,0.41544,0.41349,0.41056,0.40762,0.40469,0.40176,0.39785,0.39394,0.39003,0.38612,0.38221,0.37634,0.37146,0.36559,0.35973,0.35386,0.348,0.34213,0.33627,0.3304,0.32551,0.32258,0.31769,0.31281,0.30792,0.30303,0.29814,0.29423,0.28935,0.28446,0.27957,0.2737,0.26784,0.26393,0.261,0.26197,0.26882,0.28446,0.31183,0.34897,0.39589,0.44868,0.50147,0.55132,0.59629,0.6305,0.65591,0.67937,0.69795,0.71261,0.72434,0.73216,0.73607,0.73803,0.73803,0.73509,0.73021,0.72434,0.7175,0.70968,0.6999,0.69013,0.6784,0.66569,0.65103,0.63441,0.61681,0.59824,0.57771,0.55718,0.53959,0.52297,0.50635,0.48974,0.47507,0.46334,0.45259,0.44379,0.43695,0.43206,0.42815,0.42522,0.42229,0.42033,0.41838,0.41642,0.41447,0.41153,0.4086,0.40469,0.40078,0.39687,0.39198,0.3871,0.38221,0.3783,0.37439,0.3695,0.36364,0.35875,0.35288,0.348,0.34213,0.33724,0.33236,0.32747,0.32258,0.31769,0.31378,0.31085,0.30792,0.30401,0.3001,0.29619,0.29032,0.28446,0.27859,0.2737,0.2737,0.28055,0.29423,0.31672,0.35191,0.39785,0.45161,0.50733,0.56109,0.60899,0.65005,0.68328,0.7087,0.72727,0.74096,0.74878,0.75367,0.75562,0.7566,0.75464,0.75171,0.74585};
  //float arr[]={0.30303,0.28446,0.26979,0.25904,0.37341,0.55914,0.68622,0.73118};
  int len=sizeof(arr)/sizeof(arr[0]);

  /*for(int i=0;i<sizeof(arr)/sizeof(arr[0]);i++)  //ppg data Array display
  {
    Serial.println(arr[i]);
    delay(50);
  }*/

  //SAMPLES=len;
  for(int i=0; i<SAMPLES; i++)
    {
        microseconds = micros();    //Overflows after around 70 minutes!
        vReal[i] = arr[SAMPLES];
        vImag[i] = 0;

        while(micros() < (microseconds + sampling_period_us)){
        }
    }

  /*FFT*/
  FFT.Windowing(vReal, SAMPLES, FFT_WIN_TYP_HAMMING, FFT_FORWARD);
  FFT.Compute(vReal, vImag, SAMPLES, FFT_FORWARD);
  FFT.ComplexToMagnitude(vReal, vImag, SAMPLES);
  double peak = FFT.MajorPeak(vReal, SAMPLES, SAMPLING_FREQUENCY);

  /*PRINT RESULTS*/
  //Serial.println(peak);     //Print out what frequency is the most dominant.

  for(int i=0; i<(SAMPLES/2); i++)
  {
       /*View all these three lines in serial terminal to see which frequencies has which amplitudes*/
       Serial.print((i * 1.0 * SAMPLING_FREQUENCY) / SAMPLES, 2);
       Serial.print(" ");
       Serial.println(vReal[i], 1);  //View only this line in serial plotter to visualize the bins
       delay(50);
  }

  //delay(1000);  //Repeat the process every second OR:
  //while(1);       //Run code once
  Serial.println("Hello");
  //int freq_N=61;
  for (int i = 0 ; i < EEPROM.length() ; i++) {
    EEPROM.write(i, 0);
  }

  /*double D[3][freq_N]; //1st row for frequencies, 2nd row for magnitude, 3rd row for phase
  for(int i=0;i<freq_N;i++)
  {
    D[0][i]=-(pi/2)+i*0.1;
    double *d=fourier_tran(arr,len,D[0][i]);
    D[1][i]=*(d+0);
    D[2][i]=*(d+1);
    Serial.println(i);
    delay(300);
  }*/

  int z_crsg=zero_cross(arr,len);
  //Serial.println(z_crsg);
  //delay(1000);
  float diff_arr[len-1];   //Differenced PPG signal
  for(int i=1;i<=len-1;i++)
  {
    diff_arr[i-1]=arr[i]-arr[i-1];
  }

  int rise=rise_count(arr,len);
  int fall=fall_count(arr,len);
  float fr=(float)fall/rise;      //fall/rise count ratio
  uint16_t m=max_amplitude(arr,len);   //maximum amplitude detection
  int sc[]={0,0,0};  //sensor connectivity vector
  if(fr>1.65 && fr<2.35)
  {
    sc[0]=1;
  }
  if(m<lm)
  {
    sc[1]=1;
  }
  if(m>zero_amp)
  {
    sc[2]=1;;
  }
  int sd=sig_saturation(arr,len);
  //Serial.println(sd);
  //Serial.print(sc[0]);
  //Serial.print(sc[1]);
  //Serial.print(sc[2]);

  if(sum(sc,3)>=2)
  {
    Serial.println("Sensor well connected");
  }
  else
  {
    Serial.println("Sensor not connected properly");
  }
  delay(500);
  if(base_drift(arr,len)>=0.4612 && base_drift(arr,len)<=0.4614)
  {
    Serial.println("Motion detected");
  }
  else
  {
    Serial.println("No motion artefacts problems");
  }
  delay(500);
  if(sd==0)
  {
    Serial.println("Saturated signal");
  }
  else
  {
    Serial.println("Non-saturated signal");
  }
  delay(500);

  int d_z_crsg=zero_cross(diff_arr,len-1);

}

//Sensor connectivity detection
int fall_count(float arr[],int l)
{
  int c=0;
  for(int i=0;i<l-1;i++)
  {
    if(arr[i]>arr[i+1])
    {
      c=c+1;
    }
  }
  return c;
}
int rise_count(float arr[],int l)
{
  int c=0;
  for(int i=0;i<l-1;i++)
  {
    if(arr[i]<arr[i+1])
    {
      c=c+1;
    }
  }
  return c;
}
int max_amplitude(float arr[],int l)
{
  float h=arr[0];
  for(int i=1;i<l;i=i+1)
  {
    if(arr[i]>h)
    {
      h=arr[i];
    }
  }
  if(h>lm)
  {
    return 0;
  }
  return 1;

}

//Noise segment detection
int zero_cross(float arr[],int l)
{
  int c=0;
  for(int i=0;i<l-1;i++)
  {
    if((arr[i]==0.0) && arr[i+1]!=0.0)
    {
      c=c+1;
    }
  }
  return c;
}
int local_maxima(float arr[], int l)
{
  int frame_len=15;
  int a=0;
  int frames=l/frame_len;
  int maxima[frames];
  for(int k=0;k<frames;k++)
  {
    uint16_t h=0;
    for(int i=a;i<a+frame_len;i++)
    {
      if(arr[i]>h)
      {
        h=arr[i];
      }
    }
    maxima[k]=h;
    a=a+frame_len;
  }
  for(int i=0;i<frames-1;i++)
  {
    if(maxima[i]>lm && maxima[i+1]>lm)
    {
      return 1;
    }
    if(i<=frames-4)
    {
      if(maxima[i]<lm && maxima[i+1]<lm && maxima[i+2]<lm && maxima[i+3]<lm)
      {
        return 1;
      }
    }
    if(i<=frames-3)
    {
      if(maxima[i]<lm && maxima[i+2]<lm)
      {
        return 1;
      }
    }
  }
  return 0;
}

//Saturation detection
int sig_saturation(float arr[],int l)
{
  int c=0;
  //uint16_t lev=200000;
  for(int i=0;i<l-1;i++)
  {
    if(arr[i]<10 && arr[i+1]<10)
    {
      c++;
    }

    if(arr[i]>lm && arr[i+1]>lm)
    {
      c++;
    }
  }
  if(c>=20)
  {
    return 0;
  }
  return 1;
}

//motion detection module
double base_drift(float arr[],int l)
{
  int N=10; //N pt moving average
  int frame=l-N+1; //number of frames
  float s=0;
  double sum=0;
  for(int i=0;i<frame;i++)
  {
   s=0;
   for(int j=i;j<N+i;i++)
   {
      s=s+arr[j];
   }
   sum=sum+(s/N);
  }
  double avg=sum/frame;
  return avg;
}

int sum(int n[],int l)
{
  float s=0;
  for(int i=0;i<l;i++)
  {
    s=s+n[i];
  }
  return s;
}

float butterworth(float f, float fc,int n)
{
  float h;
  h=1/sqrt(1+pow((fc/f),2*n));
  return h;
}

double *fourier_tran(float arr[],int n,float omega)
{
   double Xr=0.00;
   double Xi=0.00;
   double DTFT[2];
   for(int j=0;j<n;j++)
   {
     Xr=Xr+arr[j]*cos(omega*j);
     Xi=Xi+arr[j]*sin(omega*j);
   }
   float X=sqrt(pow(Xr,2)+pow(Xi,2));  //Fourier transform magnitude
   float ph=-atan(Xi/Xr);  //Fourier transform phase

   DTFT[0]=X;
   DTFT[1]=ph;
   double *p=DTFT;
   Serial.println(*p);
   delay(100);
   Serial.println(*(p+1));
   delay(100);
   return p;
}
float *inv_fourier(float DTFT[][flen],int l,int flen,int n) //n is the length of the time array
{
  float arr[n];
  for(int i=0;i<n;i++)
  {
    float X=0.000;
    for(int j=0;j<l;j++)
    {
      X=X+DTFT[1][j]*cos(DTFT[2][j]+DTFT[0][j]*n);
    }
    arr[i]=1/(2*pi) * X;
  }
  float *p=arr;
  return p;
}

When I upload the code, Right after performing the FFT, the code does not display anything more, implying it ceases to execute and shows an error message - Not enough memory; see http://www.arduino.cc/en/Guide/Troubleshooting#size for tips on reducing your footprint. data section exceeds available space in board
I cannot remove either section of the code, so what do I need to change with this?

This error is normally shown while attempting to upload a sketch,  not during execution. Are you able to successfully load the sketch and the error only happens after the sensor has been read?

It happens during uploading(sorry I didn;t mention, edited).

What program and data sizes does the compiler show right after your sketch has been compiled?

Your code as posted doesn't compile. Please post the entire sketch. We cannot debug snippets.

Please provide the last lines of the output, where the program and data sizes are given.

What is SAMPLES defined as?

Okay everyone, I am posting the entire code here.

By using the F("") macro on the Serial.println(""); strings (storing them in Flash instead of copying them to RAM), I've been able to reduce the Global Variables to 2038 bytes, but that still leaves too little for running the code.

With all those floats, have you considered that an 8-bit micro with no FPU is not the optimal MCU for this.

Probably you use too much SRAM memory:
float arr[] seems to take 4 bytes (for float) * 128 = 512 bytes.
Then you have vReal and `vImage which takes 4 (double, float/doubles are the same in Arduino) * 128 * 2 (vReal/vImage) = 1024 bytes.
double vReal[SAMPLES];
double vImag[SAMPLES];

This already is 1536 bytes. The Arduino only has 2048 bytes so high likely you exceed it (including arguments passed and other globals).
arr seems to be a readonly array, so check into the use of F/PROGMEM to store them in Flash instead of SRAM (see StarCat's comment). This might get you well under the 2 KB Arduino Uno memory. Other possibilities are using a Mega which has 8 KB or use external SRAM memory but this decreases performance and takes more programming effort.
See also my anser at Optimizing code to use less Flash Memory and SRAM

See my comment: string constants (such as those used in Serial.print("");) also take up valuable RAM. You can use the F("...") macro to reduce their footprint.

Consider using one of the Teensy family.  The latest Teensy 4.0 has an onboard FPU and lots of other goodies, and runs at 600MHz. Why drive a VW when you can jump into a Ferrari for very little money?
I've been using the Teensy 3.2/3.5 modules for years, and have found them to be very stable and easy to use.

Wouldn't comparing the memory available be the most helpful selling point for this question?

Too lazy to click on the link?


text:
What are the correct pins for TWAI (CAN) on ESP32?
compared to the microchip's PICs:
pic16f's does not have an onboard CAN peripheral. so you need an SPI - CAN controller (like MCP2515).
some PIC18f's have an onboard CAN controller, and only need a CAN transceiver. In these cases there are exclusive TX and RX pins to be used.
Are there specific pins to be used as a CAN bus on esp32?
peripherals like adc, i2c and others need to use specific pins. Does this happen with CAN too?
I'm using the following configuration:
2 ESP32 devboard boards - arduino on PlatformIO
Pin 5 as TX and pin 4 as RX (already in the CAN library),
2 Sn65hvd230 transceiver modules
I looked for information about it in the documentation, but I couldn't find it.
I appreciate any help.

You can use any pins (within reason). What pins have you told it to use in your code?

You can edit your question to fill out the details that are being asked for here.

I looked for information about it in the documentation, but I couldn't
find it.

Well, some of their documentation says:

The TWAI controller’s interface consists of 4 signal lines known as
TX, RX, BUS-OFF, and CLKOUT. These four signal lines can be routed
through the GPIO Matrix to the ESP32’s GPIO pads.

And that sort of seems to be backed up by their examples that make use of TWAI_GENERAL_CONFIG_DEFAULT to generate a structure with the arguments filling fields that use gpoi_num_t.
There is documentation to the GPIO Matrix generally in the ESP32 technical reference.  It is described there as follows:

The ESP32 chip features 34 physical GPIO pads. Each pad can be used as
a general-purpose I/O, or be connected to an internal peripheral
signal. The IO_MUX, RTC IO_MUX and the GPIO matrix are responsible for
routing signals from the peripherals to GPIO pads. Together these
systems provide highly configurable I/O.

(My emphasis in the above).
And also there is a table (Table 25) in Appendix 2 of the ESP32 datasheet for the GPIO matrix.
Many of the small chips, like the PIC16F series ones, have no internal routing for peripherals, except for deciding which of one or two special functions to use rather than GPIO and ADC channels.  Most of the of the ATTiny and ATMega series AVR chips that are not in the 0- and 1- series don't.  The 1- and 0- series an a few of the older series parts (e.g. ATTiny841) give you a fixed number (usually two) pre-determined destinations to chose from for some peripherals.
This sort of thing gets more flexible as you get into larger chips, but the having that "matrix" feature that lets choose more freely is comparatively rare.  Some of the Cypress "PSoC" labeled chips have this sort of feature.

When using arduino and the esp32 core, any pin can be assigned to the builtin TWAI controller.
If you use the esp32_can library https://github.com/collin80/esp32_can
you may change the pin assignment in the following file:
C:\Users\USER\Documents\Arduino\libraries\esp32_can-master\src\esp32_can.cpp

//Set these to the proper pin numbers for you board. Set by default to correct for EVTV ESP32-Due
//rxpin       txpin
ESP32CAN attribute((weak)) CAN0(GPIO_NUM_16, GPIO_NUM_17) ;

//Select and uncomment the proper module you've got connected via SPI
//CS, INT
MCP2517FD attribute((weak)) CAN1(5, 27) ;
//MCP2515 attribute((weak)) CAN1(5, 27) ;