text:
I am trying to up the frequency everytime button is press by 100 Hz, I am using the Input pull registor
The frequency should be increased by 100 Hz whenever an external push-button on UNO digital pin 5 is depressed and then released. I think I might missing something critical.
#define LEDPIN 3
float highTime;
float lowTime;
int freq;
float period;

//uint16_t val2= pulseIn(4, HIGH);

ISR(TIMER1_COMPA_vect) { digitalWrite(LEDPIN, !digitalRead(LEDPIN)); }
void setup() {
Serial.begin(9600);
pinMode(LEDPIN, OUTPUT);
// initialize Timer1 (the 16-bit timer) using channel A output compare

TCCR1A = 0; // set entire TCCR1A register to 0
TCCR1B = 0; // same for TCCR1B
TCNT1 = 0; // initialize counter value to 0
// set compare match register for 100 Hz increments
OCR1A = 9999; // = 16000000 / (8 * 100) - 1 (must be <65536)
// turn on CTC mode
TCCR1B |= (1 << WGM12);
// Set CS12, CS11 and CS10 bits for 8 prescaler
 TCCR1B |= (0 << CS12) | (1 << CS11) | (0 << CS10);

// enable timer compare interrupt
TIMSK1 |= (1 << OCIE1A);
sei(); // allow interrupts
interrupts(); // enable global interrupts:
}
void loop() {

highTime =(pulseIn(4, HIGH));
lowTime=(pulseIn(4, LOW));
period = highTime+lowTime;
freq=1000000/period;       //getting frequency with totalTime is in Micro seconds
Serial.print(freq);
delay(1000);

Serial.print("\n");

Basically I want to turn the above code which display "100" in serial monitor with raises the frequency by 100 by a button press.
#define LEDPIN 3
const int buttonPin = 5;    // the number of the pushbutton pin

//uint16_t val2= pulseIn(4, HIGH);
// Variables will change:
int ledState = HIGH;         // the current state of the output pin
int buttonState;             // the current reading from the input pin
int lastButtonState = LOW;   // the previous reading from the input pin

// the following variables are unsigned longs because the time, measured in
// milliseconds, will quickly become a bigger number than can be stored in an int.
unsigned long lastDebounceTime = 0;  // the last time the output pin was toggled
unsigned long debounceDelay = 50;    // the debounce time; increase if the output flickers

ISR(TIMER1_COMPA_vect) { digitalWrite(LEDPIN, !digitalRead(LEDPIN)); }
void setup() {
  Serial.begin(9600);
  pinMode(LEDPIN, OUTPUT);
  pinMode(buttonPin, INPUT_PULLUP);
  // initialize Timer1 (the 16-bit timer) using channel A output compare

  TCCR1B = 0; // same for TCCR1B
  TCNT1 = 0; // initialize counter value to 0
  // set compare match register for 100 Hz increments
  OCR1A = 9999; // = 16000000 / (8 * 100) - 1 (must be <65536)
  // turn on CTC mode
  TCCR1B |= (1 << WGM12);
  // Set CS12, CS11 and CS10 bits for 8 prescaler
  TCCR1B |= (0 << CS12) | (1 << CS11) | (0 << CS10);

  // enable timer compare interrupt
  TIMSK1 |= (1 << OCIE1A);
  sei(); // allow interrupts
  interrupts(); // enable global interrupts:

}
void loop() {
  int reading = digitalRead(buttonPin);
   // If the switch changed, due to noise or pressing:
  if (reading != lastButtonState) {
    // reset the debouncing timer
    lastDebounceTime = millis();
  }
  if (reading != lastButtonState) {
    // reset the debouncing timer
    lastDebounceTime = millis();
  }

  if ((millis() - lastDebounceTime) > debounceDelay) {
    // whatever the reading is at, it's been there for longer than the debounce
    // delay, so take it as the actual current state:

    // if the button state has changed:
    if (reading != buttonState) {
      buttonState = reading;

      // only toggle the LED if the new button state is HIGH
      if (buttonState == HIGH) {
        ledState = !ledState;
      }
    }
    lastButtonState = reading;

    Serial.print(reading);
    delay(1000);
    Serial.print("\n");

  }
}

It might be a good idea to explain what happens instead of the 100Hz frequency increase you seem to be expecting. One issue is already very obvious to me: There's nothing in your loop() that changes the frequency. Just some debounce code and something that changes the variable called ledState (but nothing that actually changes the state of the LED). Where did you get this code from?

I suggest using the Bounce2 library for the button presses. It makes the handling way easier and does all the debouncing.

Your button input pin is set to INPUT_PULLUP mode so that pin will always read HIGH unless you ground it. Your button should connect the pin to ground when it is pressed.
If you do that, then the pin will read HIGH when the button is not pressed, and LOW when the button is pressed. Near the bottom of your loop() function, you test the button and toggle the LED with:
  if (buttonState == HIGH) {
      ledState = !ledState;
  }

But this toggles the LED when the button is released. Is that really what you meant?

Basically, I want it I want frequency to be increased by 100 each time I press a button

I see two sketches in your question. I was looking at the second one. How are the two related, and which one are you trying to debug?

Sorry about the confusion, basically I have to combine and edit 1st code with the button debounce code from the library function. The first code is just displays "100" hz and the second code I have use my first code to up 100 hz each time a button is pressed.

Then I believe you want to use the second code, but reverse the buttonState test - test it for LOW instead. Inside the 'if' block, where you toggle the LED, is where to put the code that increases the frequency.

I am still new to this. Can you please explain piece by piece what I need to change?

What you need to change? Take a new/clean Arduino project and first reliably read the button press. Then, you use the "tone()" function instead of manually setting registers. Build it yourself (based on examples), so you understand why/what code is there instead of copying it from the internet.

I does really seem like you're trying to learn to do too many things at once. Learn to manage the button until you're satisfied you've got it right and understand it. Then do the same thing with frequency - learn to set or change it in steps, maybe 1 second apart, using delay() to measure the 1 second. Then apply what you know to a sketch that watches the button and changes the frequency, both jobs using code you've already written (without the delay(), of course). It's much easier to learn the pieces one by one before you start putting them together.


text:
ld.exe:linker_script.ld:138 cannot move location counter backwards | ArduinoFFT Error
Board: Arduino Nano 33 BLE Sense
I'm pulling PCM data from an onboard microphone and running it through the arduinoFFT library (version 1.5.6) to obtain a spectrogram. Since the arduinoFFT library requires the data be an array of doubles, I've converted the data from short to double, and started the FFT process. The FFT.Windowing() function worked fine, but I get the error at the FFT.Compute() function call (line 77). The error goes away when I remove the function call. The error:
Found 25 compatible libraries
Scanning dependencies...
Dependency Graph
|-- <arduinoFFT> 1.5.6
|-- <PDM> 1.0
Building in release mode
Linking .pio\build\nano33ble\firmware.elf
c:/users/benlu/.platformio/packages/toolchain-gccarmnoneeabi/bin/../lib/gcc/arm-none-
eabi/8.2.1/../../../../arm-none-eabi/bin/ld.exe:linker_script.ld:138 cannot move location counter
backwards (from 000000002004a470 t
collect2.exe: error: ld returned 1 exit status
*** [.pio\build\nano33ble\firmware.elf] Error 1

And the code:
#include "Mic.h"
#include <arduinoFFT.h>

// FFT

arduinoFFT FFT = arduinoFFT(); /* Create FFT object */
/*
These values can be changed in order to evaluate the functions
*/
const uint16_t samples = 16128; //This value MUST ALWAYS be a power of 2
const double signalFrequency = 16000;
const double samplingFrequency = 16000;
const uint8_t amplitude = 100;
/*
These are the input and output vectors
Input vectors receive computed results from FFT
*/
double vImag[samples] = {0};

// buffer to read samples into, each sample is 16-bits
short* sample_buffer;

// number of samples read, read from Mic class on loop
volatile int samples_read;

// The length of the buffer to use. Currently set to 4 seconds.
int buffer_size = 16000;
double double_buffer[16384] = {};

// Instantiate
Mic mic;

// DO NOT PRINT INSIDE THIS FUNCTION - Causes it to hang.
void onPDMdata() {
  mic.sample();
}

void setup() {
  Serial.begin(115200);
  while (!Serial);
  PDM.onReceive(onPDMdata);
  PDM.setBufferSize(16128);

  Serial.println("3...");
  delay(1000);
  Serial.println("2...");
  delay(1000);
  Serial.println("1...");
  delay(1000);
  Serial.println("Listening!");

  mic.begin();
}

void loop() {

  // wait for samples to be read
  samples_read = mic.samples_read();

  // If desired buffer size is reached.
  if (samples_read >= buffer_size) {
    // Retrieves audio buffer
    sample_buffer = mic.sample_buffer();

      // print samples to the serial monitor or plotter
      for (int i = 0; i < samples_read; i++) {
        double_buffer[i] = (double)(sample_buffer[i]);
        Serial.println(double_buffer[i]);
      }

    Serial.println("---------- SAMPLE BREAK ----------");

    FFT.Windowing(double_buffer, samples, FFT_WIN_TYP_HAMMING, FFT_FORWARD);
    FFT.Compute(double_buffer, vImag, samples, FFT_FORWARD); /* Compute FFT <--------------------- THIS LINE */
    // FFT.ComplexToMagnitude(double_buffer, vImag, samples); /* Compute magnitudes */

    // delay for data collection only, comment when not collecting
    delay(1000);
    Serial.println("Listening!");

    // clear the read count and resume recording
    mic.clear_buffer();
  }
}

Where can I start to troubleshoot this issue? I've not had to deal with linker errors before, so any pointers would be greatly appreciated. Thanks in advanced!

c:/users/benlu/.platformio From that I gather that you're using platformio, which may be significant.  Have you tried building this with the the official arduino-builder/arduino-cli tools (or you know, using the IDE)?

samples = 16128; //This value MUST ALWAYS be a power of 2 - 16128 is not a power of two. (probably irrelevant)

@Mat Haha you're right! I had that set correctly, but I went on a renumbering spree trying to fix another problem... thanks for the catch!

@timemage I just gave it a try in the Arduino IDE and encountered the same exact error.

Short Version
The short answer is that you've exhausted RAM.
These two arrays alone:
const uint16_t samples = 16128;
double vImag[samples] = {0};
double double_buffer[16384] = {};

...are occupying (16128 + 16384) * 8 == 260096 bytes of memory.  There's only 262144 bytes of RAM in entirety.
The way the linker script is set up at least 1024 bytes are reserved for the stack, and there is no doubt at least another kByte in use somewhere.  In the Mbed OS and Arduino core files if nothing else.
As for why it fails only when you call Compute, that comes down to the compiler optimizer discovering that one (perhaps both) of your arrays are not actually used and so not entering into the mix when the linker is run.
Details
In theory, you should have gotten a somewhat nicer and easier to understand message from an ASSERT in the linker script:
ASSERT(. <= (ORIGIN(RAM) + LENGTH(RAM) - 1024), "heap region overflowed into stack");

So, you should have seen an error "heap region overflowed into stack" on your screen instead, which is maybe not the easiest thing for an Arduino user to decipher, but heap and stack are terms likely to be recognizable as memory-related sooner or later.
However, the linker executable shipped with the current version 1.3.2 of the Arduino core for Mbed ignores ASSERT statements completely; I have tested this (and tested my understanding of my test using an amd64 linker).  Presumably, there's a build option for the linker or a command-line or configuration file option that controls that, but I haven't found it yet.  In any case, it ignores a helpful ASSERT and instead proceeds to fail on line 138 mentioned in the error message:
 . = ORIGIN(RAM) + LENGTH(RAM) - 1024;

You can see it involves the same expression, just without a useful message if something goes wrong.  The "location counter" in the message is a linker related term that roughly means "where the next thing will be placed in memory" as it cobbles together your final executable from separately compiled chunks.  You've used so much RAM in your program that the location counter has been pushed past where the linker script wants to place the __HeapLimit symbol, 1K from the end of the MCU's RAM.  The location counter is supposed to increase monotonically.  So, evaluating this expression results in an erroneous attempt to "move location counter backwards".

Wow, thank you for the thorough answer! I tried to upvote but I don't have enough rep for it to show haha, I wanted to let you know I really, really appreciate your answer! So it sounds like I've used far too much memory, and I need to find a new approach. Thanks!

Good deal. I was going to just say "that's alright" or that you could come back if you remember. I'd forgotten there was a threshold for that but I also hadn't upvoted you're question yet.   Having done so, you should be able to upvote whatever you like.

source: Stack Exchange

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

sort: votes


text:
Expose two HID Joystick devices with single RP2040 board (Waveshare Pi Pico Zero)
I want to use a Waveshare Pi Pico Zero to connect two standard NES controllers to a computer over a single USB port.
I'm using the Waveshare RP2040 Zero board definition from https://github.com/earlephilhower/arduino-pico which seems to provide a Joystick HID library that was compatible with this Teensy targeted NES_to_USB sketch. However, that only works for a single NES controller.
I found Arduino-USB-HID-RetroJoystickAdapter that supports two joysticks or NES controllers using a single board using the MHeironimus ArduinoJoystickLibrary. Unfortunately it seems that particular Joystick library only supports ATmega32u4 based Arduino boards (e.g. Leonardo, Pro Micro).
Ask
A solution for exposing two USB HID Joystick devices on a single Pi Pico Zero board. First prize is a drop-in library like MHeironimus ArduinoJoystickLibrary that is compatible with https://github.com/earlephilhower/arduino-pico 's RP2040 core. Happy to hear of more DIY solutions too, not sure if I'll be able to follow though :)

First prize is a drop-in library ... what does that mean?

First prize is a drop-in library -- Being able to simply install an existing library into Arduino that makes a second Joystick HID device available for Pi Pico like MHeironimus's ArduinoJoystickLibrary does for ATMega32u4 based boards.

this may help... https://eleccelerator.com/tutorial-about-usb-hid-report-descriptors/

I got some useful advice about how to use TinyUSB directly from the arduino-pico maintainer. If I manage to get something working I'll write it up as an answer.

OK, I got it working, in short, select "Adafruit TinyUSB" as the USB stack and then modify the Adafruit hid_gamepad.ino  example to have two different GP reports similar to the hid_composite example. The hard bit then is dealing with the Linux kernel's stupidity and having to enable HID_QUIRK_MULTI_INPUT mode to enable multiple HID reports of the same type on a single device to work. Bit late now, will write it up properly tomorrow.

By selecting the Adafruit TinyUSB USB stack option (Tools->USB Stack->Adafruit TinyUSB) of the arduino-pico core instead of the default (Pico SDK) the USB HID descriptors can be configured directly to expose two HID gamepads.
The disadvantage of this approach is that the easy to use preconfigured devices (e.g. Joystick, Mouse and Keyboard) are not configured, but this gives you the option to use the full flexibility of TinyUSB to configure USB devices. While I've used it with my Waveshare Pi Pico Zero board it should work with any Arduino board that Adafruit TinyUSB supports.
Here is a test sketch that sets up a HID device with two gamepads similar to the "Hey how about two players?" example in https://eleccelerator.com/tutorial-about-usb-hid-report-descriptors/. I modified the Adafruit TinyUSB hid_gamepad.ino example by adding a second Gamepad report and shortening the "demo" loop to save space:
/*********************************************************************
 Adafruit invests time and resources providing this open source code,
 please support Adafruit and open-source hardware by purchasing
 products from Adafruit!

 MIT license, check LICENSE for more information
 Copyright (c) 2021 NeKuNeKo for Adafruit Industries
 All text above, and the splash screen below must be included in
 any redistribution
*********************************************************************/

#include "Adafruit_TinyUSB.h"

// NB NB!!! Select "Adafruit TinyUSB" for USB stack

// HID report descriptor using TinyUSB's template
uint8_t const desc_hid_report[] =
{
  TUD_HID_REPORT_DESC_GAMEPAD(HID_REPORT_ID(1)), // First gamepad report-id 1
  TUD_HID_REPORT_DESC_GAMEPAD(HID_REPORT_ID(2))  // Second gamepad report-id 2
};

// USB HID object. For ESP32 these values cannot be changed after this declaration
// desc report, desc len, protocol, interval, use out endpoint
Adafruit_USBD_HID usb_hid(desc_hid_report, sizeof(desc_hid_report), HID_ITF_PROTOCOL_NONE, 2, false);

// Report payload defined in src/class/hid/hid.h
// - For Gamepad Button Bit Mask see  hid_gamepad_button_bm_t
// - For Gamepad Hat    Bit Mask see  hid_gamepad_hat_t
hid_gamepad_report_t   gp[2]; // Two gamepad descriptors

void setup()
{
#if defined(ARDUINO_ARCH_MBED) && defined(ARDUINO_ARCH_RP2040)
  // Manual begin() is required on core without built-in support for TinyUSB such as mbed rp2040
  TinyUSB_Device_Init(0);
#endif

  Serial.begin(115200);
  usb_hid.begin();

  // wait until device mounted
  while( !TinyUSBDevice.mounted() ) delay(1);
  Serial.println("Adafruit TinyUSB HID multi-gamepad example");
}

uint8_t gp_i = 0;

void loop()
{
  if ( !usb_hid.ready() ) return;

  Serial.print("Testing gamepad nr: ");
  Serial.println(gp_i);

  // Reset buttons
  Serial.println("No pressing buttons");
  gp[gp_i].x       = 0;
  gp[gp_i].y       = 0;
  gp[gp_i].z       = 0;
  gp[gp_i].rz      = 0;
  gp[gp_i].rx      = 0;
  gp[gp_i].ry      = 0;
  gp[gp_i].hat     = 0;
  gp[gp_i].buttons = 0;
  // gp_i + 1 is the HID report-id, i.e. 1 for first gamepad and 2 for the
  // second, as defined in desc_hid_report[] above.
  usb_hid.sendReport(gp_i + 1, &gp[gp_i], sizeof(gp[gp_i]));
  delay(2000);

  // Random touch
  Serial.println("Random touch");
  gp[gp_i].x       = random(-127, 128);
  gp[gp_i].y       = random(-127, 128);
  gp[gp_i].z       = random(-127, 128);
  gp[gp_i].rz      = random(-127, 128);
  gp[gp_i].rx      = random(-127, 128);
  gp[gp_i].ry      = random(-127, 128);
  gp[gp_i].hat     = random(0,      9);
  gp[gp_i].buttons = random(0, 0xffff);
  usb_hid.sendReport(gp_i + 1, &gp[gp_i], sizeof(gp[gp_i]));
  delay(2000);

  // select the other gamepad
  gp_i = (gp_i + 1) % 2;
}

Linux HID Malarkey
For some reason the Linux kernel by default ignores multiple reports of the same type of HID device. I.e. a device with a mouse, keyboard and joystick device reports are no problem, but if a device has multiple of the same HID reports, say, two gamepads, Linux will only see the first instance. To enable multiple instances the HID_QUIRK_MULTI_INPUT setting must be enabled for the specific USB device.
These instructions worked on Ubuntu 22.04, you may need to adjust them for your distro.
After programming the example sketch I could see the ID of my Pi Pico USB device with `lsusb:
$ lsusb
...
Bus 001 Device 011: ID 239a:cafe Adafruit RP2040 Zero
...

Note down the USB device identifier (239a:cafe) and create a file in /etc/modprobe.d to configure the usbhid module:
$ echo "options usbhid quirks=0x239a:0xcafe:0x040" | sudo tee /etc/modprobe.d/adafruit_hid_quirk.conf

$ sudo update-initramfs -u

# Requires a reboot to take effect, e.g.:

$ sudo shutdown -r now

The 0x239a:0xcafe is from the lsusb output and 0x040 is the magic number to enable HID_QUIRK_MULTI_INPUT mode. We need update-initramfs since usbhid is usually loaded too early in the boot process for the settings from /etc/modprobe.d to take effect without it being in the initrd.
Once you have rebooted you can check if the usbhid setting took effect:
$ cat /sys/module/usbhid/parameters/quirks
0x239a:0xcafe:0x040,(null),(null),(null)

and you should see two joystick devices after programming the sketch:
ls /dev/input/js*
/dev/input/js0  /dev/input/js1

Testing
An easy way to test is to navigate to https://gamepad-tester.com/. After a short period you should see something like:

You should see Player1's values toggle and then Player2's values until you unplug your pico.

Update: more recent version of Adafruit_TinyUSB_Arduino supports having multiple HID instances (defaults to two). So to avoid the HID_QUIRK_MULTI_INPUT hack for linux, you could instead expose each controller as a different HID interface.
Here is your example updated:
#include "Adafruit_TinyUSB.h"
#if CFG_TUD_HID < 2
  #error "Requires two HID instances support. See https://github.com/adafruit/Adafruit_TinyUSB_Arduino/commit/b75604f794acdf88daad310dd75d3a0724129056"
#endif

// NB NB!!! Select "Adafruit TinyUSB" for USB stack

// HID report descriptor using TinyUSB's template
uint8_t const desc_hid_report[] = {
  TUD_HID_REPORT_DESC_GAMEPAD()
};

// USB HID object. For ESP32 these values cannot be changed after this declaration
// desc report, desc len, protocol, interval, use out endpoint
Adafruit_USBD_HID usb_hid[] {
  Adafruit_USBD_HID(desc_hid_report, sizeof(desc_hid_report), HID_ITF_PROTOCOL_NONE, 2, false),
  Adafruit_USBD_HID(desc_hid_report, sizeof(desc_hid_report), HID_ITF_PROTOCOL_NONE, 2, false)
};

// Report payload defined in src/class/hid/hid.h
// - For Gamepad Button Bit Mask see  hid_gamepad_button_bm_t
// - For Gamepad Hat    Bit Mask see  hid_gamepad_hat_t
hid_gamepad_report_t   gp[2]; // Two gamepad descriptors

void setup() {

  // Manual begin() is required on core without built-in support e.g. mbed rp2040
  if (!TinyUSBDevice.isInitialized()) {
    TinyUSBDevice.begin(0);
  }

  Serial.begin(115200);
  usb_hid[0].begin();
  usb_hid[1].begin();

  // If already enumerated, additional class driverr begin() e.g msc, hid, midi won't take effect until re-enumeration
  if (TinyUSBDevice.mounted()) {
    TinyUSBDevice.detach();
    delay(10);
    TinyUSBDevice.attach();
  }

  Serial.println("Adafruit TinyUSB HID multi-gamepad example");
}

uint8_t gp_i = 0;

void loop() {
  #ifdef TINYUSB_NEED_POLLING_TASK
  // Manual call tud_task since it isn't called by Core's background
  TinyUSBDevice.task();
  #endif

  // not enumerated()/mounted() yet: nothing to do
  if (!TinyUSBDevice.mounted()) {
    return;
  }

  if ( !usb_hid[gp_i].ready() ) return;

  Serial.print("Testing gamepad nr: ");
  Serial.println(gp_i);

  // Reset buttons
  Serial.println("No pressing buttons");
  gp[gp_i].x       = 0;
  gp[gp_i].y       = 0;
  gp[gp_i].z       = 0;
  gp[gp_i].rz      = 0;
  gp[gp_i].rx      = 0;
  gp[gp_i].ry      = 0;
  gp[gp_i].hat     = 0;
  gp[gp_i].buttons = 0;

  usb_hid[gp_i].sendReport(0, &gp[gp_i], sizeof(gp[gp_i]));
  delay(2000);

  // Random touch
  Serial.println("Random touch");
  gp[gp_i].x       = random(-127, 128);
  gp[gp_i].y       = random(-127, 128);
  gp[gp_i].z       = random(-127, 128);
  gp[gp_i].rz      = random(-127, 128);
  gp[gp_i].rx      = random(-127, 128);
  gp[gp_i].ry      = random(-127, 128);
  gp[gp_i].hat     = random(0,      9);
  gp[gp_i].buttons = random(0, 0xffff);
  usb_hid[gp_i].sendReport(0, &gp[gp_i], sizeof(gp[gp_i]));
  delay(2000);

  // select the other gamepad
  gp_i = (gp_i + 1) % 2;
}

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


text:
Per-Arduino calibration files?
I am planning on having an array of embedded devices in my garden, and each of these is going to have its own analog moisture sensor. Each moisture sensor needs to be individually calibrated.
In an ideal world, I would have the same software on each embedded device, with a configuration file holding the calibration for the attached analog moisture sensor, so that I can minimize the development and CI/CD work.
Is this possible with Arduino, or would I be better off with an embedded device with addressable flash, like an ESP32?

You may try to use the embedded EEPROM.

If the embedded EEPROM is too small, there are many serial EEPROMs for the SPI and I²C bus, giving you lots of non-volatile memory.

there are some misconception in your question. esp32 can be used with Arduino too. there are many different Arduinos with different not-volatile memory capabilities. you have to be more specific,

i would put a pot on-device since the calibration changes as the sensors oxidize and wear out (which happens in several months, even when not actively powered). They are not very accurate anyway, swinging 10% on back to back readings is considered good for all but brand new sensors.

As Edgar Bonet already mentioned, the embedded EEPROM is good to try. I give some options below though:

In case the configuration file (data) is max. 1 KB, you can use the embedded/internal EEPROM of the Arduino UNO.
In case the configuration file is larger you have multiple options:

On the ESP32 you can use 4 KB EEPROM.
If it is higher, on the ESP32 you also can use the SPIFFS file system stored in EEPROM.
For other MCUs (ESP32 included), you can use external EEPROM with various sizes, based on SPI or I2C.

If you want to use a very large configuration file, you could use an SD card, which is much slower of course, which is normally SPI based and can be used on both Arduino and ESP32.

So for a comparison between Arduino Uno / ESP32
MCU         Solution            Speed Size   External    Wearout
                                             Hardware
----------- ------------------  ----- ------ -------- --------------
Arduino     Internal EEPROM     High  1 KB      No    EEPROM Wearout
ESP32       EEPROM Simulation   High  4 KB      No    Flash Wearout

ESP32       SPIFFS File System  High  <Flash    No    Flash Wearout
                                      Size

Both        External EEPROM     High  <1MB *   Yes    EEPROM Wearout
Both        SD Card             Slow  <256GB   Yes          -

*Typically 4 KB to 1 MB, using SPI or I2C


text:
Servo keeps resetting position when there is no difference in received value?
So I'm working on a code that basically receives x and y coordinates and stores them in a variable. Whenever a coordinate is received, it goes through a conditional statement to store them in a variable, x and y, then passes it to a servo mover function. This servo motor function then moves according to what's given. It works well, but, as the values get updated over time, the servo' position always resets then goes back to where it was, again and again. Even when the coordinates are kept the same, it just resets then returns to its position over and over again.
How do I make it so that not only does it not reset then return to where it was but instead make it move to where it is supposed to go, but also to stop it from resetting anyway when the position is kept the same?
The below code is what I tried to do to basically alleviate the "position reset when coordinate is the same" issue. Unfortunately, it did not work.
bool constant = false;
// Rest of code inbetween, irrelevant to issue

// Relevant codes below
void statusCodes() {
  if (received_str == "1") {
    Serial.println("Raspberry Pi - Connection Established");
  } else if (received_str == "2") {
    Serial.println("Raspberry Pi - Data Received");
  } else if (received_str == "100") {
    Serial.println("Raspberry Pi - Status OK");
  } else if (received_str[0] == '(' ) {
    Serial.println("Coordinates Received, Ready to Delete Target!");
    if (constant == true) { // checks if this constant boolean is true
      movement = false;
    } else {
      movement == true;
    }
    int r = sscanf(received_str.c_str(), "(%d, %d)", &x, &y);
    Serial.print("X: ");
    Serial.println(x);
    Serial.print("Y: ");
    Serial.println(y);
  }
}

void onDetectTarget() {
  x = map(x, 0, 1023, 0, 180);
  y = map(y, 0, 1023, 0, 180);
  if (movement == true) {
    for (pos = 0; pos <= x; pos += 1) {
      myservo.write(pos);
      delay(15);
    }
    movement = false; // corrected
    pos = 0; // corrected

  }
}

void compareOldNew() {
  x_old = x;
  y_old = y;
  delay(900);
  if (x == x_old && y == y_old) {
    constant = true;
  } else {
    constant = false;
  }
}

In onDetectTarget() you use this for loop
for (pos = 0; pos <= x; pos += 1) {
  myservo.write(pos);
  delay(15);
}

So every time movement is true, the servo will run again from zero to the target position. So it won't "reset", but it will approach the new target value always from the zero position. You have two options to correct that:

If you just want to reach the target position, just replace the for loop with a single myservo.write(x).

If you want the servo to move slower to its new target position, you need to save the last set position of the servo in a variable and then run the for loop from that value up to the new target value. So declare a corresponding variable (for example on global scope):
  int current_pos = 0;

Then run the for loop from that position to the new target position:
  for(pos = current_pos; pos <= x; pos += 1)

And after the for loop you can set current_pos to the new servo position:
  current_pos = x;

And I guess this happens also, when the values don't change, because you never change the constant variable. You haven't implemented any check if the values are constant. (At least you haven't shown such a code and you claim the rest of the code is irrelevant)

Thanks for your response man, that was really helpful. I thought I had to use a for loop to constantly write the value but with your explanation, everything made more sense to me. As for detecting the same position, i later researched and found that you could basically use static variables to store older values, compare them and have a flag to see if they were equal or not.


text:
Can you write c code in arduino ide?
So i know that the native arduino language is written in c/c++, but does that mean that i can write pure c code in the arduino ide, or that i have to use the arduino specified language? I’m new to this and very confused, please bear with me here :’)

There is no Arduino specific language. Its just C++. Arduino just gives you a framework inside C++ to work with, like a predefined program structure (loop and setup function) and useful functions and libraries. But sure, you can use C code for Arduino - up to the point where the two languages are diverging from one another. It is not easy to spot the exact border on what of the new C features are supported, though with all older C code you should be good. Does this help? If not, can you explain more what confuses you?

Yes, you can write in pure C. Some parts of the Arduino core API are
actually defined in C, e.g. pinMode() and digitalWrite() (at least
in the AVR core). So you can use them. Other parts, like Serial, are
C++ objects, and you will not be able to use them from plain C.
The Arduino IDE, however, will insist on you writing a file with the
.ino extension, that it will compile as preprocessed C++. You do not
need to put anything in that file though. If you want to write your
whole program in pure C, you can create an empty .ino file, and in the
same folder a .c file with your whole program. In that file you can
define your own main(). If you want to use the Arduino core API
though, you should instead define setup() and loop(), and rely on
the core-provided main().


text:
Convert fuel level sender resistance ranges - good Arduino project?
I've noodled around with Arduino a bit, worked some tutorials.  I have an engineering & programming background, but electronics isn't my first language.  So apologies if this is a dumb question.
Here's the problem.  I've swapped a 2007 GM engine into an older Toyota Land Cruiser.  I need to make it compliant with the emissions equipment that was originally on the 2007 vehicle.  Most of that is pretty straight forward - catalytic converters, O2 sensors, charcoal canister, purge & vent solenoid valves, a pressure sensor.  The one bit I haven't figured out yet is fuel level.  The evaporative emissions system requires a fuel level input to the PCM (Powertrain Control Module) so it can figure out when & how to run the fuel system pressure test - the one that turns on your check engine light if your gas cap isn't on tight enough.
One solution would be to put in a GM fuel level sender ... but that involves draining the tank, dropping it, maybe cutting new holes, more wiring, etc.  I'm hoping I can fix this in software :)
The GM fuel level sending unit reads 0 ohms empty and 90 ohms full.  The existing Toyota sending unit should be 110 ohm empty and 3 ohm full.
So ... is it a feasible thing to build an Arduino based project that reads the resistance from the Toyota sender (without interfering with the Toyota gauge) and translates that to the range expected by the GM PCM?
I'm thinking something like this is the core of it: https://www.arduino.cc/en/Tutorial/LibraryExamples/DigitalPotControl  But I don't know what I don't know.
Thanks folks - additional information based on responses:
The Toyota sender is definitely a 12V two terminal unit.  Car electrical systems are nominally 12V, but typically are about 13.3V in operation.
The GM sensor is two terminal also.  According to the wiring diagram, one terminal goes to a low reference pin on the PCM and the other goes to a pin on the PCM labeled fuel level signal.
But it doesn't tell you the voltage they're applying on that pin - could be just 5V, other stuff coming out of the PCM is.  I couldn't find a test procedure either.  I'll pin that connector and see what I can measure next time I'm out there.
The fuel level signal is used for two things in the evaporative emissions (evap) system.

The evap vacuum test can only run when the tank is between approximately 1/3 to 2/3 full.
The vacuum test is calibrated against how full the tank is - lower fuel level means more air space in the tank means the pressure will change more slowly then compared to a fuller tank.

we don't have all the details of how each sensor/device "talks" to the other, but in general, yes, that's likely completely feasible to do with Arduino microcontrollers, and maybe a small amount of support hardware like a DAC (or RC filter) if needed. Break the large problem down to small steps and ask for help if you get stuck on one of them.

The Toyota sensor may be using 12V instead of 5V, which would mean you'd need to use a voltage divider to get it down to the range that the Arduino analog inputs can read.
You will need to find a digital potentiometer that can handle the voltage range that the
GM controller wants to see.  This may be 0-12V, which would be a problem since the AD5206 is only good for 5V.
However, as dandavis implies with his RC filter comment, you may be able to simulate the full 0-12V range with PWM, where the Arduino pin drives a transistor to chop up the 12V, and an RC filter smooths the result for the GM control unit.  That's probably your best approach.
Alternatively, if the GM controller is only looking for a go/no-go level, you can use the
transistor to switch in a simple voltage divider to get the right voltage from 12V.
The sensors are (presumably) just variable resistors (2-terminal) not full 3-terminal potentioneters.  They will most likely be using a series resistor to make a voltage divider, and the control unit (or gage in the Toyota) will reading the resulting voltage. You will want to either find out the value of the series resistor or measure the voltage that the gage sees.  It might already be in the 0-5V range.  The GM control unit may have the series resistor built in (or be using a current source), in which case you should measure the voltage its sensor input sees when you give it the max and min resistance.  This will be good to know when you are trying to drive it with your own circuit,

Thanks - I've added some more info to the original post based on these responses.  There's a decent chance that the GM PCM is only pushing 5V to the sensor, but I haven't been able to find it in the docs so far.  Will try to measure it.


text:
ESP32 Partition size and maximum program size #2
re. ESP32 Partition size and maximum program size
Further to the above issue:
The above is a neat little program.  However, is there any way I can reference/extract the "app0”  “partition->size” for use in an “#if” pre-processor expression?
Ideally I would want to use something like:
#if ((partition->size)<=1310720)
  #error “you must select a larger Partition-Scheme”
#endif

Or alternatively:
#if (PartitionScheme!=MinimalSpiffs)
   #error “you must select the Minimal SPIFFS Partition-Scheme”
#endif

// cf. esp32.menu. PartitionScheme.min_spiffs= Minimal SPIFFS (1.9MB APP with OTA/190KB SPIFFS)
(This is because I have a couple of projects which use 99% of the “Default 4MB with SPIFFS” program-storage-space, and will successfully compile and upload onto my ESP32 Dev Boards, but will cause the ESP32 to get stuck in a crashing boot-loop - I’m guessing the above mentioned “startup-reboot-forever loop”.  Thus for these projects I would like to add an above “#if” check to ensure I can force the compile to error/fail if the correct (larger) PartitionScheme is not selected.)

@Adriano & @6v6gt – many thanks for your below comments.

No, there is no way to find the partition size during compiling. As the code has nothing to do with the partition.

Some information from what’s been selected from the boards.txt options is available in Arduino for use in #if statements.
For example: “#ifdef ARDUINO_ NodeMCU_32S” can be used (which is taken from the “nodemcu-32s.build.board=NodeMCU_32S” option in boards.txt) to see if the “NodeMCU_32S” has been selected.  This is why I had hoped the selected “Partition Schemes” might also be similarly available for use in #if statements in some way!?

You can check the partition size once your code is running

That is what the example code in the original ESP32 Partition size and maximum program size post showed.  However in my above issue the code doesn’t run as I get stuck in the “startup-reboot-forever loop”.

..The file partitions.csv.. Arduino IDE 2.x …if you use a custom partition scheme, the IDE assumes that you are using a device with 16MB flash memory…

Thankyou – this is very useful info!

Update:  Interestingly https://github.com/HamzaHajeir/ESP32-Arduino-Builds/blob/master/tools/platformio-build-esp32.py has what appears to be a defined variable of form: "ARDUINO_PARTITION_%s" as shown below:
CPPDEFINES=[
        "HAVE_CONFIG_H",
        ("MBEDTLS_CONFIG_FILE", '\\"mbedtls/esp_config.h\\"'),
        "UNITY_INCLUDE_CONFIG_H",
        "WITH_POSIX",
        "_GNU_SOURCE",
        ("IDF_VER", '\\"v4.4.5\\"'),
        "ESP_PLATFORM",
        "_POSIX_READER_WRITER_LOCKS",
        "ARDUINO_ARCH_ESP32",
        "ESP32",
        ("F_CPU", "$BOARD_F_CPU"),
        ("ARDUINO", 10812),
        ("ARDUINO_VARIANT", '\\"%s\\"' % env.BoardConfig().get("build.variant").replace('"', "")),
        ("ARDUINO_BOARD", '\\"%s\\"' % env.BoardConfig().get("name").replace('"', "")),
        "ARDUINO_PARTITION_%s" % basename(env.BoardConfig().get(
            "build.partitions", "default.csv")).replace(".csv", "").replace("-", "_")
    ]

But this “platformio-build-esp32.py” file seems very different from the default https://github.com/espressif/arduino-esp32/blob/master/tools/platformio-build.py version, and it is beyond my capabilities to incorporate this
 "ARDUINO_PARTITION_%s" % basename(env.BoardConfig().get(
  "build.partitions", "default.csv")).replace(".csv", "").replace("-", "_")

line into the default espressif file!

If anyone want's to know how to do this, an example (using board="ESP32 Dev Module") is:
// #if ARDUINO_PARTITION_default // from boards.txt: "esp32.menu.PartitionScheme.default=Default 4MB with spiffs (1.2MB APP/1.5MB SPIFFS)"
//  #error "please change to a larger Partition Scheme"
#if ARDUINO_PARTITION_no_ota // from boards.txt: "esp32.menu.PartitionScheme.no_ota=No OTA (2MB APP/2MB SPIFFS)"
  Serial.println("ARDUINO_PARTITION_no_ota being used");
#else
  #error "wrong Partition Scheme has been selected"
#endif

With the ESP32 Arduino core 3.x it is relatively simple in that you include a custom partition file (partitions.csv) in the sketch folder. Of course you (probably still) have to remember to select "custom partition" in the tools menu. The file partitions.csv is even respected by the Arduino IDE 2.x for uploading sketch data, that is to the littleFS partition. However, currently, if you use a custom partition scheme, the IDE assumes that you are using a device with 16MB flash memory for the % usage statistics generated by the compilation process.

No, there is no way to find the partition size during compiling. As the code has nothing to do with the partition.
You can check the partition size once your code is running.


text:
The control function is not sending out correct values
#include <MIDI.h>

int scale = A4;
int oct = A2;
int potval, octval,octval2=0;
int newnote, prevnote = -1;
int newpotval,prepotval=-1,potval2=0;
int trigr = 7;   // Ultrasonic right
int echor = 9;
int trigl = 8;   // Ultrasonic left
int echol = 10;
int pingr,pingr1=0, pingl,pingl1=0, cc, octave, p;
int button = 13; // Button
int buttonval = 0;

MIDI_CREATE_DEFAULT_INSTANCE();

void setup() {
  pinMode(scale, INPUT);
  pinMode(oct, INPUT);
  pinMode(trigr, OUTPUT);
  pinMode(echor, INPUT);
  pinMode(trigl, OUTPUT);
  pinMode(echol, INPUT);
  pinMode(button, INPUT_PULLUP);

  //MIDI.begin();
  Serial.begin(9600);
}

void loop() {
  potval = analogRead(scale);
  delay(5);
  octval = analogRead(oct);
  delay(5);
  octave = octavenum(octval);
  p=scaleval(potval,potval2);
  Serial.println(p);
  delay(50);

  control();
  delay(50);
  //notesscale(p);
  //delay(50);
}
void notesscale(int p) {
  digitalWrite(trigr, LOW);
  delayMicroseconds(30);
  digitalWrite(trigr, HIGH);
  delayMicroseconds(30);
  digitalWrite(trigr, LOW);

  pingr = pulseIn(echor, HIGH);

  Serial.print("Right ultrasonic values: ");
  Serial.println(pingr);
  delay(100);

  if(abs(pingr - pingr1) > 200) {
    if (pingr <= 850) {            // Condition 1
      newnote = p;
    }
    else if (pingr <= 1450) {       // Condition 2
      newnote = p + 2;
    }
    else if (pingr <= 2050) {       // Condition 3
      newnote = p + 4;
    }
    else if (pingr <= 2650) {      // Condition 4
      newnote = p + 5;
    }
    else if (pingr <= 3250) {      // Condition 5
      newnote = p + 7;
    }
    else if (pingr <= 3850) {      // Condition 6
      newnote = p + 9;
    }
    else if (pingr <= 4450) {      // Condition 7
      newnote = p + 11;
    }
    else if (pingr <= 5050) {      // Condition 8
      newnote = p + 12;
    } else {
      newnote = -1;
    }

    if (prevnote != newnote) {  // Ensure newnote is valid
      if (prevnote != -1) {
        MIDI.sendNoteOff(prevnote, 127, 1);
        delay(20); // Adjust delay if needed
      }
      MIDI.sendNoteOn(newnote, 127, 1);
      delay(20);
      prevnote = newnote;
    }
    pingr1 = pingr;
    delay(10);
  }
}
int octavenum(int octval) {
  if(abs(octval-octval2)>20){
    if (octval >= 0 && octval <= 93) {
      octval2=octval;
      return -2;
    }
    else if (octval >= 94 && octval <= 186) {
      octval2=octval;
      return -1;
    }
    else if (octval >= 187 && octval <= 279) {
      octval2=octval;
      return 0;
    }
    else if (octval >= 280 && octval <= 372) {
      octval2=octval;
      return 1;
    }
    else if (octval >= 373 && octval <= 465) {
      octval2=octval;
      return 2;
    }
    else if (octval >= 466 && octval <= 558) {
      octval2=octval;
      return 3;
    }
    else if (octval >= 559 && octval <= 651) {
      octval2=octval;
      return 4;
    }
    else if (octval >= 652 && octval <= 744) {
      octval2=octval;
      return 5;
    }
    else if (octval >= 745 && octval <= 837) {
      return 6;
    }
    else if (octval >= 838 && octval <= 930) {
      octval2=octval;
      return 7;
    }
    else {
      octval2=octval;
      return 8;
    }

  }
  return octval2;

}

int octaveOffset(int octave, int baseNote) {
  return baseNote + (octave + 2) * 12;
}

void control() {
  digitalWrite(trigl, LOW);
  delayMicroseconds(20);
  digitalWrite(trigl, HIGH);
  delayMicroseconds(20);
  digitalWrite(trigl, LOW);
  pingl = pulseIn(echol, HIGH);

  Serial.println("left ultrasonic values");
  Serial.println(pingl);

  if (pingl >= 0 && pingl < 250) {
    MIDI.sendControlChange(14, 0, 1);  // (cc channel, cc value, channel)
  }
  else if (pingl > 2000 && pingl < 4000) {
    MIDI.sendControlChange(14, 127, 1);
  }
  else if (pingl >= 250 && pingl <= 2000) {
    cc = abs((127.0 / 1750.0) * (pingl - 250));
    MIDI.sendControlChange(14, cc, 1);
  }
  else if(pingl>5000){

  }
  delay(10);
}

int scaleval(int potval,int potval2){
  if(abs(potval-potval2)>50){
    if (potval <= 86) {
      Serial.println("C maj/A min");
      newpotval = octaveOffset(octave, 0);
    }
    else if (potval <= 172) {
      Serial.println("C# maj");
      newpotval = octaveOffset(octave, 1);
    }
    else if (potval <= 258) {
      Serial.println("D maj");
      newpotval = octaveOffset(octave, 2);
    }
    else if (potval <= 344) {
      Serial.println("D# maj/C min");
      newpotval = octaveOffset(octave, 3);
    }
    else if (potval <= 430) {
      Serial.println("E maj/C# min");
      newpotval = octaveOffset(octave, 4);
    }
    else if (potval <= 516) {
      Serial.println("F maj/D min");
      newpotval = octaveOffset(octave, 5);
    }
    else if (potval <= 602) {
      Serial.println("F# maj/D# min");
      newpotval = octaveOffset(octave, 6);
    }
    else if (potval <= 688) {
      Serial.println("G maj/E min");
      newpotval= octaveOffset(octave, 7);
    }
    else if (potval <= 774) {
      Serial.println("G# maj/F min");
      newpotval= octaveOffset(octave, 8);
    }
    else if (potval <= 860) {
      Serial.println("A maj/F# min");
      newpotval = octaveOffset(octave, 9);
    }
    else if (potval <= 946) {
      Serial.println("A# maj/G min");
      newpotval = octaveOffset(octave, 10);
    }
    else {
      Serial.println("B maj/G# min");
      newpotval = octaveOffset(octave, 11);
    }
    if (newpotval != prepotval) {
      prepotval = newpotval;
      return newpotval;
    }
    potval2=potval;
    return prepotval;
  }
}

/// the correct output that is required is different values ranging from 0 to 127 outputted through midi cc 14 but when the control() function is being called then the program outputs random values through random midi cc channels the other functions are outputting correct values which are  called prior to control(),also i monitored the outputs using the serial monitor which gave me correct values for the octave and p and the distance measured using ultrasonic sensor.Also when i am using hairless serial-midi converter to monitor my midi messages.

Sorry, a code-only question nearly always has too few information. What do you mean by "correct" and "not correct"? Where is it sending the values? How do you check on the send values? How do you know the inputs are correct? What exactly is the input in your code? What have you done to narrow down the problem? Please add some text to your question (by editing it, not in the comments) to answer these questions. That might enable us to help you.

looks like the octavenum() function was written by a different person than scaleval() ... octavenum() has more cumbersome logic, with unnecessary  code ... scaleval() is more elegant in its logic, with simpler code .... octavenum() could easily be the same way

when the function is being called ... which function? ... please clarify exactly what the program is doing ... the other functions are outputting correct values ... which functions?

reduce your code ... send some fixed values ... do you receive those values correctly?

cc = abs((127.0 / 1750.0) * (pingl - 250)); With some boards abs() does not work correctly on floats. See https://forum.arduino.cc/t/abs-function-does-apparently-not-work-on-floats/658747/ . It may not be your problem and may not be your board.

pingl = pulseIn(echol, HIGH); This may be a problem depending on which board you have since pingl is defined as int which may overflow after about 32,000 (us) on an 8bit cpu. (pulseIn returns microseconds and, by default, times out at 1 second).  It is probably best to define pingl as unsigned long (uint32_t)

Agreed with @6v6gt, pulseIn() return duration in uS with unsigned long which is 32-bit, not a 16-bit int.


text:
Controlling Vintage floppy drives
After researching a solution to a problem I want to solve, I'm hoping the third time posting is a charm. :)
I'd like to use an Arduino to control a vintage floppy disk drive. I'm looking to use it as a testing platform to first make sure that various basic functions (Motor spinning, stepping in, stepping out,going back to track 0) all work, and as a bonus I'd like to be able to test writing and reading data. Hopefully by using the Arduino I have more control over the functions instead of attaching it to a system and trying "dir" or "copy" and hoping things are happening correctly.
In my research, I found an article from 2014 (Controlling Floppy Disk Drive with Arduino and another in 2017 Simple reading and writing on Floppy Disk. The first article never was able to get the basic functionality working, the second article (Based on the first one) seemed to skip over the basic functions and go straight to reading/writing.
The first poster's issue was -

I am expecting the Index to pulse when the disk motor makes a rotation, and for Track 0 to change when I am at the outside of the disk, but they are both always LOW. Am I missing something?

They don't specifically say it, but they never confirmed the stepping was working.
I'm using the code directly from the first article with the suggested tweak by @geometrikal as -
//https://arduino.stackexchange.com/questions/3702/controlling-floppy-disk-drive-with-arduino
//
//constants
static const int IN = LOW;
static const int OUT = HIGH;
static const int pulseDelayTime = 6;

//pins
int indexPin = 2; //8 on the drive INDEX
int track0Pin = 3; //26 on the drive. TRACK 0
int dirPin = 6; //18 on the drive. DIRECTION
int stepPin = 7; //20 on the drive. STEP
int motorEnableBPin = 9; //16 on the drive. MOTOR ENABLE B

unsigned long motorSpinTime = 1000UL; //in ms

void setup() {

  //initial delay
  delay(3000);

  //setup serial monitor
  Serial.begin(9600);

  //setup pins.
  pinMode(dirPin, OUTPUT);
  pinMode(stepPin, OUTPUT);
  pinMode(motorEnableBPin, OUTPUT);
  //pinMode(indexPin, INPUT); - Original code from @jeffctown
  //pinMode(track0Pin, INPUT); - Original code from @jeffctown
  //Code suggested by @geometrikal in https://arduino.stackexchange.com/a/3706/106869
  pinMode(indexPin, INPUT_PULLUP);
  pinMode(track0Pin, INPUT_PULLUP);
  //turn the motor off initially
  digitalWrite(motorEnableBPin, HIGH);

  //print state here.
  printState("Setup done.");

  //spin the disk some.
  printState("Begin to spin motor");
  spinMotorForThisManyMs(motorSpinTime);
  spinMotorForThisManyMs(motorSpinTime);
  printState("Done spinning motor");

  //step read/write head all the way in.
  stepAllTheWayIn();

  //spin the disk some more.
  printState("Begin to spin motor");
  spinMotorForThisManyMs(motorSpinTime);
  spinMotorForThisManyMs(motorSpinTime);
  printState("Done spinning motor");

  //step read/write head all the way out.
  stepAllTheWayOut();

  //spin the disk even more.
  printState("Begin to spin motor");
  spinMotorForThisManyMs(motorSpinTime);
  spinMotorForThisManyMs(motorSpinTime);
  printState("Done spinning motor");

  //never completes.
  waitForIndex();
}

void loop() {
}

//spins the disk motor for a number of ms and prints the state
void spinMotorForThisManyMs(unsigned long msToSpin) {

  //start spinning
  digitalWrite(motorEnableBPin,LOW);

  //delay.. keep printing the state
  unsigned long maxTimeMs = millis() + msToSpin;
  while(millis() < maxTimeMs ) {
    printState("Spinning");
  }

  //stop spinning
  digitalWrite(motorEnableBPin,HIGH);
}

//step the read/write head all the way to the center
void stepAllTheWayIn() {
  for(int i=0;i<100;i++) {
    printState("Stepping In");
    stepInALittle();
  }
}

//step the read/write head all the way to the outside
void stepAllTheWayOut() {
  for(int i=0;i<100;i++) {
    printState("Stepping Out");
    stepOutALittle();
  }
}

//print the state of the index and track
void printState(const char* charPrint) {
  Serial.print(" Index:");
  Serial.print(digitalRead(indexPin));
  Serial.print(" Track:");
  Serial.print(digitalRead(track0Pin));
  Serial.print(" ");
  Serial.println(charPrint);
}

//move the head towards the outside a little
void stepOutALittle() {
  digitalWrite(dirPin,HIGH);
  stepPulse();
}

//move the head towards the center a little
void stepInALittle() {
  digitalWrite(dirPin,LOW);
  stepPulse();
}

//pulse the step pin
void stepPulse() {
  digitalWrite(stepPin,LOW);
  delay(pulseDelayTime);
  digitalWrite(stepPin,HIGH);
}

//waits for the index to trigger. this never gets completed.
void waitForIndex() {

  printState("beginning to wait for index pin to pulse");

  //start spinning
  digitalWrite(motorEnableBPin,LOW);

  //wait for pulse
  while(digitalRead(indexPin));
  //wait for end of pulse 0
  while(!digitalRead(indexPin));

  printState("end of waiting for index pin to pulse");

  //stop spinning
  digitalWrite(motorEnableBPin,HIGH);
}

And the same exact pinouts from the first article too.

For track stepping, it first sets-
pinMode(stepPin, OUTPUT);

and later on does -
digitalWrite(dirPin,HIGH);
// Step routine
digitalWrite(stepPin,LOW);
delay(pulseDelayTime);
digitalWrite(stepPin,HIGH);

It should step out, and by setting dirPin to LOW it should step in. Neither one of these functions seem to be happening with my setup. I've checked the wiring 1/2 a dozen times and reviewed the code with no luck.
The second article (Based on the first) was concentrating more on read/write, which means they may not have paid attention to stepping.(Not to mention they weren't able to write).
I checked the pinning, and the code, and there isn't anything I can understand that might be causing the issues.
Wondered if anyone understands why what's expected isn't happening or has found or created their own code to be able to put a drive through some of its paces.
Thanks, Tuc

You say you can't understand what it causing the issue.  What issue?  You never say what you are trying to do or make happen or what is going wrong.  Are you trying to write files to a floppy drive?

Wondered if anyone has found a solution to this issue. that is a chat suitable for a forum, but this site is not a forum ... a question about the problem is required here

Welcome to SE/Arduino! You took the [tour], which is rare. Very good! Now you might want to read "[ask]" and other pages of the [help], too. This is not a forum to discuss things. This site collects questions and answers.

If you [edit] your post and make it an on-topic question, it will be re-opened. Please read the reason of closing and how to resolve carefully.

Please extend your code snippets to a minimal, complete, and reproducible sketch. And please add a schematic of your hardware setup.

Reading and writing data is probably not possible. Double density 5 inch floppy drives required a byte of data every 12us and I expect 3.5 inch drives would be faster. Generally DMA hardware is required.

@kiwiron This is true, but only if you want to read and write in the same format as standard systems. You can use any other serial protocol. In the eighties some DIY computers used common asynchronous serial signals. So in principle it is possible to read and write.

@kiwiron - totally understand.  This is for a rig just to check functionality.  This is not for trying to store something. In the end I just want to make sure basic and possibly advanced functions work on a drive before even attaching to my host system. Again, not actually using this for storage,  just to verify basic operations of a drive function.

@thebusybee - will this be reopened?

Probably, the question needs multiple votes. It received mine already.

How is this easier than just attaching the drive to a computer and testing it?

@Delta_G - I have better control over the drive than just typing DIR :3 and hoping.

Do you?  Right now you don't have any control.

Now that we see your complete source, the error seems clear. You don't enable the drive at all. You can check by the drive's activity LED at its front.
Each floppy drive has a "drive select" signal. According to the Wikipedia page about the floppy disk drive interface there are two pins, DRVSA and DRVSB on pins 14 and 12, respectively.
You need to select the drive matching the "motor enable" you use, so it's DRVSB on pin 12. Please make sure that your drive is jumpered to be drive B. Otherwise use the pins labeled "A".
For a first experiment I would reduce the sketch to simply "blink" the drive select signal. Only if you see that on the drive's front, do the next experiment, for example enable the motor.

Actually I experimented with the built-in drive of my Atari 1040STFM way back in the eighties. A little assembly program used a PWM algorithm to modulate the drive's LED slowly from off to on and back. It was spooky.

So I added a pin from the Uno on pin 10 to the DS line on my device. I set the signal HIGH on startup, and LOW when I was doing a drive specific action. I got the stepper running fine on a Gotek, and a 5.25, but had an issue with an 8". The 8" was recently repaired, so it should be working, but don't know if it needs anything extra that the Gotek/5.25 aren't looking for.


text:
How do I fix display showing random pixels on ST7789V2 LCD Module?
Problem Description:
I’m trying to interface a Waveshare 1.69-inch LCD module (ST7789V2 driver, 240x280 resolution) with an Arduino UNO board. I’ve connected all the necessary ports as per the documentation, and I’m using Adafruit’s ST7789 library for the code. However, instead of displaying an image or text, the screen only shows random pixels.

Hardware Setup:

Arduino UNO
Waveshare 1.69-inch LCD with ST7789V2 driver (240x280 resolution)

Wiring:

VCC to 5V
Ground to Ground
DIN to D11 (MOSI)
CLK to D13 (SCK)
CS to D10
DC to D7
RST to D8
BL to D9

Code:
    #include <SPI.h>
    #include <Wire.h>
    #include <Adafruit_GFX.h>
    #include <Adafruit_ST7789.h> // Library for the ST7789 display

    // Define the pin connections
    #define TFT_CS     10
    #define TFT_RST    8
    #define TFT_DC     7

    // Initialize the Adafruit ST7789 object
    Adafruit_ST7789 tft = Adafruit_ST7789(TFT_CS, TFT_DC, TFT_RST);

    // this is the bitmap, change this variable for your specification.
    const uint16_t myBitmap [] PROGMEM =

    {
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0xfe,
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0xfe, 0x00, 0x00,
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xff, 0xff, 0x80, 0x00, 0x00, 0x00,
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xf8, 0x1f, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00,
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
        0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x99, 0x9b, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
        0x00, 0x00, 0x00, 0x07, 0x99, 0x99, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xff,
        0xff, 0x9f, 0xe6, 0x67, 0xf9, 0xff, 0xff, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xff, 0xff, 0x9f,
        0xe6, 0x67, 0xf9, 0xff, 0xff, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x61, 0xff, 0xff, 0xff, 0xff,
        0xff, 0xff, 0x86, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x61, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
        0x86, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1e, 0x1e, 0x7f, 0xff, 0xff, 0xfe, 0x78, 0xf8, 0x00,
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
        0x00, 0x00, 0x00, 0x00, 0x00, 0x1e, 0x1e, 0x7f, 0xff, 0xff, 0xfe, 0x78, 0xf8, 0x00, 0x00, 0x00,
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
        0x00, 0x00, 0x00, 0x01, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00,
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
        0x00, 0x01, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
        0x1f, 0xfe, 0x66, 0xc6, 0x7f, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0xfe,
        0x66, 0xc6, 0x7f, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0xff, 0xff, 0xff,
        0xff, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0xff, 0xff, 0xff, 0xff, 0xe0,
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xff, 0xff, 0xff, 0xff, 0x80, 0x00, 0x00,
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xff, 0xff, 0xff, 0xff, 0x80, 0x00, 0x00, 0x00, 0x00,
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
        0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0xf6, 0xe7, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
        0x00, 0x00, 0x00, 0x7f, 0xe6, 0xe7, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
        0x00, 0x7f, 0xff, 0xff, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f,
        0xff, 0xff, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xff, 0xf7, 0xf7,
        0xff, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xff, 0xff, 0xff, 0xff, 0x80,
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x86, 0x7f, 0xfe, 0xc1, 0xe0, 0x00, 0x00,
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0x7f, 0xfe, 0x00, 0xe0, 0x00, 0x00, 0x00, 0x00,
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
        0x00, 0x00, 0x00, 0x00, 0x1e, 0x00, 0x7f, 0xfe, 0x00, 0x78, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
        0x00, 0x00, 0x1e, 0x00, 0x7f, 0xfe, 0x00, 0x78, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
        0x7e, 0x19, 0xff, 0xff, 0x98, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0x19,
        0xff, 0xff, 0x98, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x80, 0x61, 0xbf, 0xfb,
        0x86, 0x01, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x80, 0x61, 0xbf, 0xfb, 0x86, 0x01,
        0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xe0, 0x61, 0xbf, 0xfb, 0x86, 0x07, 0x80, 0x00,
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
        0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x80, 0x61, 0x9f, 0xf9, 0x86, 0x01, 0x80, 0x00, 0x00, 0x00,
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
        0x00, 0x00, 0x00, 0x01, 0x87, 0xe1, 0x9f, 0xf9, 0x87, 0xe1, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00,
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
        0x00, 0x07, 0xff, 0xe1, 0x9f, 0xf9, 0x87, 0xf1, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07,
        0xff, 0xe1, 0x9f, 0xf9, 0x87, 0xf8, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0xff, 0xe1,
        0x9f, 0xf9, 0x07, 0xf8, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0xff, 0xe0, 0x1f, 0xf8,
        0x07, 0xff, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0xff, 0xe0, 0x1f, 0xf8, 0x07, 0xff,
        0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xff, 0xe0, 0x1f, 0xf8, 0x07, 0x9f, 0x80, 0x00,
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
        0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xff, 0xe0, 0x1f, 0xf8, 0x07, 0x9f, 0x80, 0x00, 0x00, 0x00,
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
        0x00, 0x00, 0x00, 0x00, 0x01, 0xe0, 0x1f, 0xf8, 0x07, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
        0x00, 0x00, 0x01, 0xe1, 0x9f, 0xf9, 0x07, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
        0x01, 0xe1, 0x9f, 0xf9, 0x87, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xe1,
        0xff, 0xff, 0x87, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xe1, 0xff, 0xff,
        0x87, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xf1, 0xff, 0xff, 0x9f, 0x80,
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xff, 0xff, 0xff, 0xff, 0x80, 0x00, 0x00,
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0xff, 0xff, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00,
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
        0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0x7f, 0xfe, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
        0x00, 0x00, 0x00, 0x7f, 0xfe, 0xff, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
        0x00, 0x7f, 0xfe, 0x7f, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,

    };

    // Function to draw the bitmap stored in PROGMEM
    void drawCustomBitmap(const uint16_t* bitmap, int16_t x, int16_t y, int16_t w, int16_t h) {
      // Loop through the rows and columns of the bitmap
      for (int16_t row = 0; row < h; row++) {
        for (int16_t col = 0; col < w; col++) {
          // Calculate the index in the bitmap array
          int16_t index = row * w + col;

          // Read the 16-bit pixel color from the array stored in PROGMEM
          uint16_t color = pgm_read_word(&bitmap[index]);

          // Draw the pixel on the screen with the retrieved color
          tft.drawPixel(x + col, y + row, color );
        }
      }
    }

    void setup() {
      // Your setup code here
      tft.init(240, 280);

      // Use your custom function to draw the bitmap array
      drawCustomBitmap(myBitmap, 0, 20, 240, 280); // Replace 240 and 135 with actual width and height of your bitmap

       tft.enableDisplay(true);
    }

    void loop() {
      // Loop code if necessary
    }

What I’ve Tried:

Double-checked the wiring: All connections seem secure and match the
pin mapping specified above.
Library setup: Using the recommended Adafruit ST7789 library and
initializing it according to the documentation.
Tested with basic code: Tried displaying simple text and solid colors
to rule out complex image issues.
I used this website to convert an image into a bitmap: image2cpp

Whatever image you generated contains 1664 bytes of data only (and it is not as what you declare as uint16_t, it is actually 1664 uint8_t). A full image for a 240x280 display as per your custom function trying to iterate would require 240x280=67200 bits or 8400 bytes for a 8-bit Monochrome image.

@hcheung This is an independent issue. Even then at least some pixel would show some non-random pattern. So the actual issue is somewhere else.

Please add the "solution" to your actual answer. It does not belong in the question.

SOLUTION:
I edited my setup() to use a tft built in function I didn't previously know about. I made the following edit:
void setup() {
  // Your setup code here
  tft.init(240, 280);
  delay(500);

  // Clear the display to black
  tft.fillScreen(ST77XX_BLACK);

  // Draw the bitmap at position (x, y) = (10, 10)
  // tft.drawBitmap(10, 10, myBitmap, 240, 280, ST77XX_WHITE);
  tft.drawRGBBitmap(10, 10, myBitmap, 240, 280);

  tft.enableDisplay(true);
}

This worked with the monochrome bitmap I was using previously. I then tested it with a bitmap generated from an otoscope image in rgb and it did not work at all since Arduino's memory is limited. I'm going to try with a Raspberry pi next.

This answer is not complete as it lacks context. See my other comment.

Your answer could be improved with additional supporting information. Please [edit] to add further details, such as citations or documentation, so that others can confirm that your answer is correct. You can find more information on how to write good answers in the help center.


text:
BH350 Strain gauge Arudino naon
I have changed the strain gauge of BH350 modules with another strain gauge of equal 350 ohm strain gauge, but after the change, the readings are only 1 or 2. It's like there is no strain gauge connected to the module. Even when I tried to increase the current by nob of the module, no reading was there. Any Solution? Please help.
Or if there is any other solution like can i connect 2 wire strain gauge to HX711 module?

where did you get the picture?  ... it says that you are not allowed to copy it

Come on, it is just a picture. Give me an answer if you have one. It not an area69 project

you cannot post copyrighted material here

The HX711 is optimized for 4-wire or 3-wire configurations, and directly connecting a 2-wire strain gauge to the HX711 may not yield the expected results. Moreover, the HX711 module requires a complete Wheatstone bridge configuration to operate, and if your strain gauge is not configured within the bridge, you may not get any meaningful readings.
Connecting a 2-wire strain gauge directly to the HX711 module could further complicate the situation, and it is not recommended.
You can refer to pages 5 and 6 of this HX711 pdf document:
https://www.jakelectronics.com/pdf/datasheets/8465c9553d41406e1902912c0f8c8929?product=aviasemiconductor-hx711-68717131


text:
Arduino to run and LED strip of up to 100m
I am working on a project to run an RGB strip around a large room and have the colour change driven by an Arduino Uno. I have encountered a number of issues and am looking for clarification.
The first strip I used was a 12V strip at 1A/m. This would work fine except the power requirement is slightly ridiculous and it seems I need to put my array of MOSFETs in at every power injection point.
This was when I decided to experiment with a 5V addressable strip to do it. Working with a 5V system gave me more ease as the power requirements are lower and the parts list is also minimal, but after some research, it seems that the signal line will degrade significantly on that many WS2812B's / line length.
I suppose I could but a transistor inline every n-number of 5m strips (similar to the power injectors), however I would like to ask for some opinions from the community around other issues I may encounter, and whether or not this is the right solution for the job.
The scope of the project is to hold a colour for a number of seconds then switch colour based on a predefined program. This program is defined on an external device that uses the Arduino's serial port to communicate the desired colour. The implementation itself is very simple.
The main issues I can see are the power requirements (I think I have this sorted for the 5V version but not the 12V version) and getting the signal to the final LED. On a 60 LED/m strip this could be in the order of around 6000 LED's and that seems like a lot.
What are your views/recommendations?
Cheers!

What makes you think the signal will degrade over that number of LEDs?

@Majenko I read it on the arduino forum somewhere. If that is not the case then that is cool. I think the post on the forum said they were getting interference from other wires in the vicinity of the signal line (maybe power or something) I'm essentially a n00b at this - it has been ages since I messed around with micro electronics and I'm re-learning everything again lol. If my assertions are incorrect I am happy for constructive criticism :)

The WS2812B datasheet states: Built-in signal reshaping circuit, after wave reshaping to the next driver, ensure wave-form distortion not accumulate. -- Basically the "distance" is only ever the distance between two adjacent LEDs.

@Majenko That's awesome news. So there shouldn't be too much of an issue driving that many LED's with a Uno? From my research, 60(LED's per metre) * 100 * 3(bytes/LED) gives me 18K of memory needed to store the state. Since the Uno has 32K I should be fine right?

... I think there are some youtube videos that show where voltage drop can affect color on long runs. Probably due to PWM variations due to slight voltage differences betwen the power injection point and the far end.  Also the longer the string of addressable LEDs the larger the amount of data to be sent the slower the rate of intentional change.  I would at least run larger power wires and inject power at several locations.

"... gives me 18K of memory needed to store the state. Since the Uno has 32K I should be fine right?"  Will all the LEDs be set the the same color?  I'm not sure how the driver works, but if you set all the addressable LEDs to the same color then why would you need to store each LED's color setting?  Of course, if all the LED were set to the same color you could get by with a much cheaper RGB&Gnd type LED strip.

Seems I remembered incorrectly - it only has 2k of RAM. So that is a problem. I think I need to jump up to the MEGA or the Nano 33 to store the values. The main reason it is storing the values @st2000, is that I am using the FastLED library to do this. But you are right - if I write the 'setter' code myself then I won't need the memory.

@st2000 I was using a 12V -RGB setup before but the power requirements and  my assumed need for a box of MOSFET's every-so-often deterred me from the idea. 100m of lights at that voltage required 100A of power and that seemed like it was dangerous. The system needs to be foolproof and stable.

@st2000 ... that's why I think the addressable option is better cause they just plug into each other and have power at each connection to inject power when required.

... I've never put much thought into a 100 meter run of addressable LEDs so don't feel comfortable saying what you propose will work or not (I think it will, but you may have some unexpected problems you will have to work thought).  Consider searching for people who "trim their houses" w/these types of LED strips.  Some of the problems they have worked through may interest you.

Signal degradation: This is pretty much not a problem, as long as you just send the signal through the LED strip. Each WS2812B chip has circuitry to ensure, that the output signal is shaped correctly. As long as you don't have long runs of pure cable for the signal in between you will be good.
Power requirements: Using WS2812Bs lets you ditch your own MOSFET driving circuits, though the overall power will be in the same range. When you drive the LEDs at full intensity white (R, G and B full intensity) each LED will draw about 60mA. With 60 LEDs/m and 100m length you have 6000 LEDs, which equates to a max current of 360A. Thats a lot. You will probably need multiple power supplies. I think you can get 5V power supplies with like 70A from typical retailers. Of course there are also some which, provide more, but you will also want to reduce the max length of cable the current will flow (putting each power supply near the strip part, that it is powering).
Also you should inject power to the strip every 1 to 1.5m to stay safe. Above that you can see degradation after some time (I injected every 2.5m once and the LEDs still work, but you can see the degradation on the strip material and it gets hot when being on).
IMPORTANT: When you buy the typical brick power supplies, they often use a barrel connector. But with these currents you shouldn't use them. In one of my own projects I currently have to replace those with better connectors, because the barrel connectors started to melt from the heat and smoked. I know use small banana connectors, which are also used for drone motors. They can handle way more current without getting hot. Also your cable should be thick enough to handle the current without getting hot.
Controller:
As you already know you will get into the memory limit with the Uno. Your assessment of the needed memory for using the FastLED library (or the NeoPixel library) is correct. You will need 18kB only for the buffer (not including the rest of the programs variables).
Now you can either

change to a microcontroller with enough RAM to handle that buffer
or send the data out on demand instead of first filling it into a buffer.

The first option will definitely be easier with programming. The second option will require you to do some handwork. The libraries that I know of all use a buffer. Though I've once read this article about the timing on WS2812B LEDs. In the end the author also links to his working code, which puts out the data directly without using a buffer. You might wanna have a look at it. Also you could look at the code of the FastLED or Neopixel library. They of course also have the code to send the data and you might be able to copy and adapt that code for your case.

Thanks for this - really informative. The power requirement is what scares me really. I was thinking of a 8-10A power supply every 5 metres product I might use - the manufacturer says 6-8A should run 5m.

use 10A per 5 meters at least. A power supply can get less efficient when near max capacity and it will get rather hot with 8A. Used 8A supplies with the project I mentioned and they get really hot. The power is nothing really dangerous. With 5V you cannot do much harm to humans. Though you need to make sure, that every part of the project is able to handle way more current than you need. If they get too hot they might cause a fire.

And please don't use the barrel connectors, that are used by most brick power supplies. Those cannot handle currents over a few amps. Mine were melting with 8A, so I currently replacing them with small banana connectors.

And that is my ultimate worry. It will switch between colours every 40 secs or so but I can program the system that I am building to either exclude white or make it dull. The only colours I am supporting are RGB values from here so I don't think the power requirements will be huge but will still be enough to require multiple injection points.

With a 100m strip you are already in a really high territory, even when you dim the LEDs down. In this situation I would plan with the full possible power. It gets more safe, when your system is able to handle more power, but needs less. And it gets less safe, when your system can handle less power and the needed power approaches the max power. So planing with a big headroom is more safe.

RE: barrels - Yeah the final product will probably use spade connectors like this to deliver the power. That should be fine I think.

Personally for power I use small buck regulators (3A) at regular intervals (depending on density of LEDs) and feed those from higher voltage, lower current, power sources. For example a 24V 10A supply should be able to run up to about 36A at 5V spread across 12 24V->5V buck regulators and not lose as much over the power wires.

@Majenko this was a topic of discussion between me and a mate. Using 48V (something like PoE) to run some wire around the building and then regulating it down to the correct voltage.

Re “this article about the timing on WS2812B”: I have used the technique described in that article, and it worked pretty well even on an ATtiny13A, which has only 64 bytes of RAM.

Also a third option for solving the RAM problem: use multiple microcontrollers and implement some form of communication bus between them.

@Majenko this has been on my mind - but I really want to avoid it lol. The system is gonna be rolled out to places I can't debug at so debugging a dead LED or PSUI is easy. But trying to get someone to reset all controllers because there is a comms issue is not in scope of the project.


text:
Is there a standard way to describe devices?
I'm new to Arduino. I'm curious whether there is a standard way to record the plan of a device—for instance, if I wanted to share it or communicate the design to other people. I realize the short answer here might be, “yes, make a circuit diagram.” Are there perhaps widely used tools for producing those, perhaps with add-ons for Arduino boards? (I'd prefer a more semantic representation than, say, making a diagram in Inkscape.)

There is no plugin to a program like Inkscape - as far as I know. It doesn't make much sense to have one. With an Arduino circuit you normally want to show the real electrical connections. A block diagram without real electrical connections doesn't help much in reproducing the project. You can do it, but you will have to do it on your in in a graphic program. I think this is only helpful for rather big projects, where each block contains not only the Arduino but also many further components of that functional unit in your project.
To show the circuit you basically have 2 options:

A wiring diagram: This is an image, mostly created via the software Fritzing, which shows a breadboard and the components of the project placed on it. The electrical connections are represented by colored lines. This is good for beginners, who cannot yet read a schematic and want to reproduce the circuit on their own breadboard. Though wiring diagrams, especially Fritzing, is only standard in the Arduino/Beginner world. The more you get into professional realm, the less you will see them. They look like this (please note the internal connections, that a breadboard has in its numbered rows):

A schematic: A schematic is the standard way of describing any electronic circuit. For example look at the Arduino Uno schematic. Every part is represented by a symbol with pins. The pins get connected with lines (representing wires or PCB traces). There are many different softwares for creating schematics, for example Eagle, KiCAD, EasyEDA and Altium Designer. You can choose yourself what to use. Look at the options, that the softwares provide. Some are premium but have free options, others (like KiCAD) are open source. I personally use KiCAD. At least for KiCAD you can download part repository files (like this one), which include Arduino boards, so that you can place them directly on your schematic. I'm sure there are similar resources for other programs as well. Export the resulting schematic to PDF or an image format so that everyone can read the schematic without having your program installed.
An additional benefit in creating a schematic is, that all these programs also support creating a PCB layout from the schematic. So it gets easier to design a PCB from your circuit for DIY or ordered production.

As the OP asked for a “semantic“ representation, I would add that a schematic is “semantic” in the sense that, in its original format, it can be used to generate a netlist, which is useful to make sure one gets the PCB connections right.

You can get KiCad for the downloading. It works great from schematic capture through generating the Gerber files to get PCBs manufactured. It will take a little practice to get the hang of it.


text:
Integer division
I want to divide two integers and get how often one of them fits into the other completely, so there will always be an integer as an output. In python you do this kind of operation with //.

So... just pure integer division (doing division without the rest behind the decimal point)? Thats just the division operator / with integers. For example 13/4 will get you 3 (because both operants are integers, so the part behind the decimal point is ignored). Is that what you mean?

cast both numerator and denominator to integers of appropriate type and use division: (int)num/(int)den produces an int result (2-byte signed in arduino).   you may want to use stdint.h (aka cstdint) types like int16_t which make the types clear regardless of compiler (int is 4-byte signed in some places)
you may find that casting at math operations is useful in other scenarios too.  for example, sometimes you want to handle integer rollover (255+1 will roll to 0 if they are 1-byte unsigned).

In C++, the integer division operator is /, and the floating point
division is also /. The compiler chooses according to the types of the
operands:

if either or both operands are floating points numbers, you get a
floating point division

if both operands are of some integer type, you get an integer
division.

Thus:

5.0/2.0, 5.0/2, 5/2.0 all have the same value, namely 2.5

5/2 is 2.


text:
Arduino port not discovered with bootloader / Did I fry my board?
I have a Arduino Nano 33 BLE that I've been using for a while. I usually upload new programs to the board through USB with the board in a bootloader loop. The other day this stopped working. The board can successfully be put in the bootloader (slow pulsing light), however it does not appear as a TTY device on my computer. The last program I put on my device still works, and successfully outputs serial output (and I can even connect to the bluetooth module).
This leads me to believe my board is working, though I don't understand why I cannot upload via the bootloader. Interestingly the bootloader running makes the board pretty hot (hotter than my program running, is it in an infinite loop or something?).
I thought the bootloader might've been corrupted, so I re-uploaded the board's bootloader via a raspberry pi over OpenOCD (it's possible I did this incorrectly?). Now the device remains in the bootloader no matter what.
I'm wondering if it's possible I fried just the USB part of my board? is that likely? I did hook up the board to a wall adapter that is rated 12V @ 1.5A. The issue seemed to occur after this. Is the board able to handle 1.5A? Do I need to use an additional circuit to properly power the board off of this power adapter?

So I cannot even attempt to upload it, as the board is not available for selection. A ls /dev/tty.* results in no devices.

If you put that 12V to Vin pin, it should be fine, to any other pin it means death.

@KIIV thanks! that's what I expected, I didn't see a max current for that pin, and assumed that shouldn't be a problem (it should just draw the amount it needs, no?)

Yes, I did see that, the detail data sheet says the Vin feeds into a 3.3V power which has a max current of 1A. Is it possible I messed something up there?
I have a new board on the way, my bigger concern is not also bricking that board, if I have indeed bricked my current board.

I'd expect smoke to appear if an Arduino gets fried with 12V and that should most likely have killed the entire controller.

Ya that's what I was thinking as well -- can anything explain the behavior I'm seeing then?

You can try to program it via an ISP programmer (for example using another Arduino). You can also reflash the bootloader that way. If the ISP programming fails, then your controller is dead.

Would that be any different than flashing a bootloader via OpenOCD?

I see Input Voltage (limit)  21V. Flashing over SWT is 'ISP'

you say "The last program I put on my device still works, and successfully outputs serial output". how it there is no port?

Over the TX and RX lines I can get serial output, but the on-board USB does not show up as a port

is the USB cable 'power only'?

It is not, same cable worked previously with the same board (I've tried other cables as well). I think I screwed up the bootloader now, probably used OpenOCD incorrectly. I have a BMP on the way. Maybe I can revive it that way. At this point it's to satisfy my curiosity


text:
Coding for RTC and stepper motor
How easy is it to create a code using an RTC to rotate the stepper motor one way at a specific time and back the other way at a specific time? and that time being charged different months of the year. how would I go about this?
I want to make an automatic chicken door, to open in the morning and close at night.
Thanks

please do not ask opinion based questions .. those are off topic here ... anyway, what is the point of asking how easy something is? ... how is an answer like somewhat easy even useful?

develop the project in sections .... start with rotating the stepper to desired positions ... next, add code tbat rotates the stepper when a button is pressed ... next, replace button control with time based control

This question is difficult to answer because it depends on your skills. For an absolute beginner it can be complicated, for someone with a little more experience it will be easy.

code is finite, and better yet logical.  should be "easy" compared to the hardware portion where the possibilities are nigh infinite and chaotic.  If hardware is done, tested, and reliable, then just loop over: reading rtc (1), deciding on an action such as deep sleep or running motor to change door (2), and performing the action (3).  Break each step down into simpler actions based on searches, but if you properly tested the hardware already, you should have code to break up and reuse from when you did that.

I am assuming that you want to make a clock. To do that you need to find a gear ratio where 1 revolution of the motor equals 60 seconds, and then make the gear ratios for the minutes and horse from that. Then you can use the RTC to spin the motor by 6 degrees every second. If you are not making a clock, please be more descriptive.

Spend some time searching the web, I have seen several solutions one of them even did a chicken door.