text:
Arduino, problem with interrupt and SSD1306 OLED
I'm not that good at this. Calculates RPM through Peripheral Speed and Interrupt.
Everything works fine when I show this in the IDE with Serial.print without OLED. When I connect an SSD1306 OLED I2C, the interrupt stops working. No serial.print.
If I uncomment the display.display(), Same problem with display.setRotation(90): everything is fine and serial.print starts working, but of course not the OLED.
In the code I have a void addressing, visadisplay(). If I put this addressing in void loop () then everything works but then there is a risk of unsynchronization, wrong values. I have also removed visadisplay(); without change.
Help...
#include <SPI.h>
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>

#define SCREEN_WIDTH 128 // OLED display width, in pixels
#define SCREEN_HEIGHT 32 // OLED display height, in pixels

// Declaration for an SSD1306 display connected to I2C (SDA, SCL pins)
#define OLED_RESET -1 // Reset pin # (or -1 if sharing Arduino reset pin)
#define SCREEN_ADDRESS 0x3C ///< See datasheet for Address; 0x3D for 128x64, 0x3C for 128x32
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);

// Function for serial display.
// Connections for Nano.
// Hall sensor connection: (Signal out) --- (D2).
// Display connection: (SDA) --- (4A) / (SCL) --- (A5)

volatile unsigned long PulsTid = 0UL;
volatile unsigned long StartTid = 0;
volatile unsigned long SlutTid = 0;
volatile unsigned long CalcTid = 0;
volatile float omkrets = 7.5;
volatile float HastighetPerferi = 0;
volatile unsigned long Rpm = 0;
volatile float Vinkel = 0UL;

void isr() { // interrupt service routine
  Vinkel = 0;
  StartTid = millis();
  CalcTid = SlutTid;

  detachInterrupt(0);             //detaches the interrupt while calculating

  PulsTid = (StartTid - SlutTid);
  HastighetPerferi = (omkrets / PulsTid);
  SlutTid = StartTid;
  Rpm = ((HastighetPerferi / (omkrets / 1000) * 60) / 2); // Calculate speed

  visadisplay();
  attachInterrupt(0, isr, FALLING);  //attaching the interrupt again
}

void visadisplay(void) {
  Serial.print("Varvtal: ");
  Serial.println(Rpm);

  display.setRotation(90);
  display.clearDisplay();
  display.setTextSize(1);              // Text size.
  display.setTextColor(SSD1306_WHITE); // White text.
  display.setCursor(0, 0);             // Start position
  display.println("RPM: ");
  display.setCursor(40, 10);
  display.setTextSize(2);
  display.print(Rpm);
  display.display();
}

void setup() {
  Serial.begin(115200);
  attachInterrupt(0, isr, FALLING);  //attaching the interrupt

  //SSD1306_SWITCHCAPVCC = generate display voltage from 3.3V internally
  if (!display.begin(SSD1306_SWITCHCAPVCC, 0x3C)) { // Address 0x3C for 128x32
    Serial.println(F("SSD1306 allocation failed"));
    for(;;); // Don't proceed, loop forever
  }
}

void loop(){
}

I would guess, that the display code needs interrupts to work during its execution, which is not the case inside an ISR. Serial will just put the data into the buffer, which then gets pushed out later via interrupts. Try to set a flag inside the ISR and then execute the display code in the main loop, if the flag was set

You don’t have to disable and re-enable the interrupts inside an ISR (in fact, you really shouldn’t). Also, an ISR should be very short (as few instructions as possible) and yours isn’t. Take @chrisl ‘s advice and set a flag inside the ISR, test for the flag in the main loop and leave handling of the display code to the main loop.

I2C communication (usually) requires interrupts. You can't use interrupts inside an interrupt. Ergo, you can't use I2C communication inside an interrupt. There's very little you can do in an interrupt.

Your problem is (most likely) that you are doing everything from an interrupt. That is not only bad practice, but on Arduinos it is generally impossible.
On small microcontrollers you typically only have one interrupt priority (occasionally two). That means that only one interrupt can run at a time, and if an interrupt is running then no other interrupt can interrupt it.
So anything that relies on interrupts to operate can never be used inside an interrupt service routine, or it will never function.
That includes things like delay() and, depending on the implementation, such things as Wire (I2C) and SPI.
Instead your ISR really should be as short as possible. It should at most do any short calculations and store results, and then indicate (through the use of a semaphore) to the main thread that it should do some work.
The simplest "fix" to your problem would be to move visadisplay() into loop() and in isr() simply set a bool flag when there is data to display. Your loop() then checks that flag and, if set, resets it and calls visadisplay().
Also, you don't need to detach and re-attach the interrupt all the time - if the ISR is running then interrupts can't happen anyway.
// ... snip ...
volatile bool doDisplay = false;

void isr()          //interrupt service routine
{
  Vinkel = 0;
  StartTid = millis();
  CalcTid = SlutTid;

  PulsTid = (StartTid - SlutTid);
  HastighetPerferi = (omkrets/PulsTid);
  SlutTid = StartTid;
  Rpm = ((HastighetPerferi/(omkrets/1000)* 60)/2);  //Calculate speed

  doDisplay = true; // Signal to the main thread there's data to display
}

// ... snip ...

void loop() {
    if (doDisplay) {       // If there is something to display
        doDisplay = false; // then clear the flag for next time
        visadisplay();     // and display the data.
    }
}

I tested with an LCD display and SPI connection instead of I2C. Then everything works as it should. A bit sad that you have to use circumventing solutions on such elementary needs to connect a display.

About rotating text on OLED, rotation codes are 0, 1, 2, 3
(see Adafruit web site).
So your code should look like:
  Serial.print("Varvtal: ");
  Serial.println(Rpm);

  display.setRotation(1);
  display.clearDisplay();


text:
Missed call to GSM
I want to give missed call to GSM module; how to do that? Whenever I call to GSM module, after 3 RINGs, it should be disconnected. How to do this?
#include <SoftwareSerial.h>

String string = "";
int ring=0;
int i;
//Create software serial object to communicate with SIM800L
 SoftwareSerial mySerial(3, 2); //SIM800L Tx & Rx is connected to Arduino #3 & #2

void setup() {
  //Begin serial communication with Arduino and Arduino IDE (Serial Monitor)
  Serial.begin(9600);

  //Begin serial communication with Arduino and SIM800L
  mySerial.begin(9600);

  Serial.println("Initializing...");
}

void loop() {
  serialEvent();
  if (ring >= 1) {
    Serial.write("ATH");
  }
}

void serialEvent() {
  while (mySerial.available()) {
    char read_char = Serial.read();
    string += read_char;
    i++;

    if (string[i - 4] == 'R' && string[i - 3] == 'I' && string[i - 2] == 'N' && string[i - 1] == 'G') {
      ring = 1;
    }
  }
}

You're reading from Serial after checking mySerial.available(). Use a better name for the serial connected to the GSM module to avoid confusing yourself.

source: Stack Exchange

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

sort: votes


text:
LCD display interfaced with Arduino Uno not displaying values
I am a beginner on Arduino. I have a project that I will only be using: a heart rate sensor whose values I am displaying on an LCD display. The code compiles and uploads once I set my project up, but the value doesn't appear on my LCD screen.
#include<LiquidCrystal.h>
#include <TimerOne.h>

LiquidCrystal lcd(13, 12, 11, 10, 9, 8);
int HBSensor = 4;
int HBCount = 0;
int HBCheck = 0;
int TimeinSec = 0;
int HBperMin = 0;
int HBStart = 2;
int HBStartCheck = 0;

void setup() {
  lcd.begin(20, 4);
  pinMode(HBSensor, INPUT);//heartbeat sensor
  pinMode(HBStart, INPUT_PULLUP);
  Timer1.initialize(800000);
  Timer1.attachInterrupt(timerIsr);
  lcd.clear();
  lcd.setCursor(0, 0);
  lcd.print("Current HB: ");
  lcd.setCursor(0, 1);
  lcd.print("Time in Sec :");
  lcd.setCursor(0, 2);
  lcd.print("HB per Min :0.0");
}

void loop() {
  if (digitalRead(HBStart) == LOW) {
    lcd.setCursor(0, 3);
    lcd.print("HB Counting ..");
    HBStartCheck = 1;
  }
  if (HBStartCheck == 1) {
    if ((digitalRead(HBSensor) == HIGH) && (HBCheck == 0)) {
      HBCount = HBCount + 1;
      HBCheck=1;
      lcd.setCursor(14, 0);
      lcd.print(HBCount);
      lcd.print(" ");
    }
    if ((digitalRead(HBSensor) == LOW) && (HBCheck == 1)) {
      HBCheck=0;
    }
    if (TimeinSec == 10) {
      HBperMin=HBCount * 6;
      HBStartCheck=0;
      lcd.setCursor(14, 2);
      lcd.print(HBperMin);
      lcd.print(" ");
      lcd.setCursor(0, 3);
      lcd.print("Press Button again.");
      HBCount = 0;
      TimeinSec = 0;
    }
  }
}

void timerIsr() {
  if (HBStartCheck == 1) {
    TimeinSec = TimeinSec + 1;
    lcd.setCursor(14, 1);
    lcd.print(TimeinSec);
    lcd.print("");
  }
}

Please don't use capslock. Thats the equivalent of shouting at us and makes the text difficult to read.

Is this still only in the proteus simulation, or do you now use real hardware? And have you tried following the advice from the comments of your other question? Like declaring variables, that are used inside an ISR, as volatile?

No i only using proteus simulation, this code is for hardware i tried the use it in proteus , ( Like declaring variables, that are used inside an ISR, as volatile? ) No sir i am a very beginner can you show me how please??and thank you

You're doing too much inside the ISR so it takes too much time. Also, the HBStartCheck and TimeinSec variables are changed inside the ISR but not declared volatile so the rest of your code might not see any changes to these variables. change the int HBStartCheck = 0; and int TimeinSec = 0 at the start of your code into volatile int HBStartCheck; and volatile int TimeinSec;. Also move the lcd.setCursor() and lcd.print() out of the ISR and do this inside of loop ().

i remove  TimeinSec=TimeinSec+1;     lcd.setCursor(14,1);     lcd.print(TimeinSec);     lcd.print(""); in the loop and add volatile in TimeinSec = 0 and HBStartCheck = 0 but still doesn't work

does the oscilloscope show a signal on channel B?

Did you configure the sensor with a heartbeat signal (from a hex file)? I ask because in the first question, you provide osci printouts and they were flat. So your sensor has no output.

I think that you may be not paying attention to details ... in your previous question, you connected a battery backward ... in this question, you connected to one pin and configured the sketch for another pin

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


text:
Arduino measuring high-voltage electric fence
I would like to know if someone has experience with measuring high voltages using an Arduino.
I know you can use resistors to lower the voltage, however.
I want to be able to measure the pulses of an electric fence used to prevent farm animals from escaping. These pulses are high-voltage and will not always be a similar voltage. I want to read these voltages, to scan for differences.
So, I wondered if someone has done something like that, and if the Arduino gets weird when it gets a voltage above 5 V at a low amperage on its analog port.
--here some possible solutions for those wanting to know the answer--
-mostly based on comments and answers below-

Using resistors as a voltage divider while keeping an eye on the maximum spark gap distance and capacitive coupling.
using a transformer/coils to reduce the voltage.
using a high voltage probe to measure it.
using neon bulbs or other light sources to measure it.
charging a capacitor and measuring discharge time with high resistance(only works for the total power)

-this list is meant as a summary of what is discussed further ideas and solutions are still welcome-

Duh, that's typically a couple thousand volts. I fear a simple resistor won't do, since the voltage is high enough to cause severe interference or jump trough the air. And that would destroy your equipment quite spectacularly.

Do you really want to measure it, like proportionally, or just see that it's still operating?

I don't think that the high voltage is the problem. I grew up on a farm in Germany and There were many occations to experiment with el. fences, when I was a child ;-). The voltage is not high enough to "jump" over more than a fraction of a millimeter, and that only with a perfect ground. I would say the only thing that jumps is the farmer if, he touches the fence. Yes, I've tried it. Yes, I jumped.

One of the problems is the variations in the voltages. You can be sure that all pulses are of the same amount. You could build a voltage divider, sometimes it is sufficient, sometimes not.  The next problem is the length of the pulse, How can you be sure you get the peak voltage, if you only take probes at discrete times? So I would say the arduino allone is not fast enough to give you reliable results.

If you are fit in electronics, build a voltage devider with two high watt, low value resistors. Add a peak detektor to it and meassure the voltage with your arduino. Use a 5V Zehner diode to protect the Arduino pin from high voltage. Zehner diodes are slow, so you might want to use N shottkey diodes that add to about 5V.

i think that you can buy a fence tester that contains a neon bulb ... use a photo sensor to detect the light from the lamp

@PeterPaulKiefer: at 10kV, the pulse can build a spark of at least 10mm, which is absolutely significant given the physical size of a breadboard or a resistor.

Typically you would use a long chain of resistors. The voltage across each one is then below the maximum rated voltage for that individual resistor (and any distances involved). However a transformer may be a better solution to give galvanic isolation.

@PMF A 10kV signal with a high frequency can do that (e.g. Tesla coils). A single pulse has not the power and not the time to to ionize the air. The pulse can create a high potential electric field, but the wires are too small to take much voltage from that. If you keep the arduino 10 cm away from the fence wire, the field has nearly no impact. A direct voltage coupling whith a voltage devider is the only way to build a cheap measurement solution, as long as you get it to measure fast enough to find the pulse peak or use a peak detector.

Using a trafo is diffficult, because you have no sine wave, so the trafo has impact of the shape of the signal. Then it gets difficult to reconstruct the peak. And as I understand, the different peak voltages of the pulses are the goal of this exercise.

Ahh, one thing I forgott to mention. Of cause the Arduino is not the only one who is in danger. 10kV (even  a short pulse) can kill you. E.G. if your the owner of a weak heart. So, be carefull.

@PeterPaulKiefer I just want to throw in another point: you don't need to measure pulses. The voltage on an electrical fence is static: when touching the wire, you get a shocked immediately - you don't need to wait for the next pulse. Pulses are only used to recharge the fence's capacity.

@SimSon As soon as you add the voltage devider to the wire it will be discharged. You will only get the peak voltage at the peak of the pulse. You need to meassure exactly at the peak of the pulse or you use a peak detector, if you want to measure the differences in the peak voltage, like IMHO the OP asked.

In my experience electric fences put out high voltage AC. That's the easiest, low-tech way to boost voltage, after all - a transformer many time more windings in the secondary than in the primary would boost an AC input to high voltage quite simply.

https://forum.arduino.cc/index.php?topic=18043.0

While my question describes an electric fence to make it more usable and understandable for everyone, the actual system uses a specific coreless coil for self-inductance. it runs from 12v and is meant to detect objects that respond to the magnetic or electromagnetic charge. since the coil itself has quite high resistance(+-50 ohm) the output current and voltage are quite safe and below an actual electric fence. I can make sparks with it to the battery terminal by slide-disconnecting it I get at most around 2mm sparks(see st. jacobs ladder). normal sparkgabs work up to around 0.1mm at most.

@timemage I need to actually measure it to detect the difference in self inductance. so I can use that to detect objects and their relative distance/location.

@PeterPaulKiefer perhaps I might be able to get it stable enough with some small capacitors then I can measure the total energy instead of the voltage which in this case should give good results as well that way I stabilize the highest peaks and it might better suit the arduino's peak.

You are talking about measuring 2 to 10 kV pulses, with about 1 to 5 J of energy per pulse.
The maximum current may be very low, but the voltages you want to measure are very high, and will very probably damage your Arduino without proper measures.
You will at least need a voltage divider to reduce the voltage the Arduino sees to 5 V (or 3.3 V for some Arduinos) to be able to make a measurement with the Arduino's ADC.
The voltages are high enough to bridge a fair distance with a spark; they could well bridge a physically small resistor or the distance between two connections on your breadboard or PCB.
To be honest, I think you shouldn't go anywhere near such voltages with an Arduino, unless you know exactly what you are doing when preparing the signal for an Arduino's ADC pin.

Consider purchasing a high voltage probe for a VOM. They are very high in resistance, if you go low you will drain all the energy out of the fence.  Nice part they are designed for this type of voltage, not a kludge device. This would go in series with a load resistor then measure the voltage across the load resistor which has one end grounded to the fence ground. International code limits the voltage to 10KV some countries it is lower.

I think perhaps I might make a transformer like some have told in the comments, and then use a divider with extra isolation. some peak detection would be great however in a way where it would only pass through the highest differences.
I was also when starting to think about this project thinking about designing my own computer for it or using analogue equipment, however, I thought that Arduino would be great to use because I can also easily perform all other kinds of instructions.

@Gil I will try that, I have some laying around anyway so testing it would be great. I might also try making a custom one since that would make it more readable and less tape and wire.

When you say 'scan for differences', do you mean differences along the fence, or something else?  Do you plan to use the Arduino as a portable voltmeter?  If so, buying a HV probe for a standard voltmeter sounds a lot more practical.
However, if you plan to install multiple sensor points along the fence so that you can continually monitor pulse amplitudes along the fence, then that is a different kettle of fish, especially if you are thinking about outdoor use over a long fence length.
Can you elaborate a bit, please?

I mean to use a system similar to an electric fence. but more compact and coil like to use the self-inductance to measure changes in nearby metallic or water like objects. since in versions where I manually feel for the differences in shock values it seems to respond really good to metals where a simple coil would give clearly feelable different shock intensity when I introduced small metal objects, at ranges my commercial metal detector can not even detect them.

Note that the coil I use at the voltage and the maximum allowed charge and discharge time cycle is tuned to be rather safe even when put in massive cast iron. I would of course not recommend anyone to use its hands at a high voltage circuit, especially when not sure it is tuned properly to around half of the intentionally dangerous values.


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

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

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

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

Well, some of their documentation says:

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

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

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

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

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

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

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


text:
How to you initialize a reset on a sht30 digital thermometer?
I have a sht30 that will output correct temperature readings for about 5 min and then will drift off.
So I'm trying to hit the reset every few seconds to keep the readings accurate.
I am on a nano connecting d4 to the sht30 reset pin, but I don't appear to be resetting. My temp still drifts.
How do you correctly hit the reset on a sht30?
code:
#include <Wire.h>

// SHT31 I2C address is 0x44(68)
#define Addr 0x45

int reset_pin = 3; // reset pin is set to d4 on board.
int counter = 0; //reset counter

void setup()
{
  // Initialise I2C communication as MASTER
  Wire.begin();
  // Initialise serial communication, set baud rate = 9600
  Serial.begin(115200);
  delay(300);
}

void loop()
{
  unsigned int data[6];

  // Start I2C Transmission
  Wire.beginTransmission(Addr);
  // Send 16-bit command byte
  Wire.write(0x2C);
  Wire.write(0x06);
  // Stop I2C transmission
  Wire.endTransmission();
  delay(300);

  // Start I2C Transmission
  Wire.beginTransmission(Addr);
  // Stop I2C Transmission
  Wire.endTransmission();

  // Request 6 bytes of data
  Wire.requestFrom(Addr, 6);

  // Read 6 bytes of data
  // temp msb, temp lsb, temp crc, hum msb, hum lsb, hum crc
  if (Wire.available() == 6)
  {
    data[0] = Wire.read();
    data[1] = Wire.read();
    data[2] = Wire.read();
    data[3] = Wire.read();
    data[4] = Wire.read();
    data[5] = Wire.read();
  }
  // Convert the data
  int temp = (data[0] * 256) + data[1];
  float cTemp = -45.0 + (175.0 * temp / 65535.0);
  float fTemp = (cTemp * 1.8) + 32.0;
  float humidity = (100.0 * ((data[3] * 256.0) + data[4])) / 65535.0;

  // Output data to serial monitor
  Serial.print("Temperature in Celsius :");
  Serial.print(cTemp);
  Serial.println(" C");
  Serial.print("Temperature in Fahrenheit :");
  Serial.print(fTemp);
  Serial.println(" F");
  Serial.print("Relative Humidity :");
  Serial.print(humidity);
  Serial.println(" %RH");
  delay(500);
  if(counter == 25){
    digitalWrite(reset_pin, HIGH); // sets the digital pin 13 on
    delay(1000);            // waits for a second
    digitalWrite(reset_pin, LOW);  // sets the digital pin 13 off
    delay(1000);
    counter  = 0;

  }
  counter++;
  Serial.println(counter);
}

The RESET pin is active low, not active high.

I'm hitting both so it should be resetting. Interesting.

Except you end up on LOW so it remains stuck in reset. You need to end up on HIGH.

You should really be asking yourself why it's drifting though... it's rated at 0.03C/year drift according to the datasheet...

@Majenko It will drift 10 degrees in a matter of 15 min. I gave up on that and ordered different units all together. This is a last ditch effort to get something useful out of the device.

You need to give a brief LOW pulse, not a long HIGH pulse:
In setup:
pinMode(reset_pin, OUTPUT);
digitalWrite(reset_pin, HIGH);

When you want to reset:
digitalWrite(pin_reset, LOW);
delay(1);
digitalWrite(pin_reset, HIGH);


text:
Storing data from Arduino without Serial print- High Sample rate
For my work, I need to acquire data at a high sample rate (>100kSa/sec) using Arduino Portenta H7, which has 3 X 16-bit ADCs. Portenta H7 has STM32H747XI microcontroller. I don't want to use Serial.print command as I came to know that this command takes much time to execute, which makes achieving the targeted sample rate impossible.  What are the other possible ways to store the data from Arduino while maintaining this high sample rate? For example, saving the data and then printing them all at once at the end of testing( 3-5 second testing period). e.g. using an SD card or through saving in Arduino internal memory? Can you suggest techniques employed for high-sample rate data acquisition from Arduino?

How big is a "sample"? How many samples before "end of testing"?

Thank you. I want to acquire 2 analog signals - 16 bit each- at a rate of 100kSa/sec. Probably 3-5 seconds testing period.

So about 2 megabytes. What kind of Arduino? "Arduino" is a brand name, not a product. Why does it have to be an Arduino?

@ElliotAlderson that lowercase "portenta" seems to be Arduino Portenta H7 which uses STM32H747XI, with 1 MiB of RAM, of which most should be accesible via DMA. That's an amazingly powerful MCU with lots of memory, the Portenta seems like a neat little devkit. Basit please edit relevant details into your question.

@JanDorniak Thanks, my brain completely skipped over that.

Serial.print() is slow when it involves an actual UART, but it should be fairly fast when run via a direct USB connection.  Your board clearly has direct USB access to the main MCU which would be the sensible way to do this (even if you buffer in RAM first), what's not entirely clear is if that is the USB channel on the USB-C connector and supported by the Arduino Serial class, or a different one only available on a header.  Ultimately you might do better with some more traditional streaming solution, eg based on a Cypress FX2 USB-FIFO or the like.

The Portenta has a beast of an  STM32H7 Cortex M7 and a minimum of 8M bytes of external SDRAM in addition to the 1M on-chip.
You need to capture 2channels x 2 bytes x 100K/s x 5s = 2M bytes of data, so storing it on the on-board RAM and spitting it out later seems like a viable and low-risk approach.
A slow serial link might take a few minutes to transmit 2M bytes of data, but you have various other options if that is objectionable.

Thank you Spehro. My apologies if it's too basic a question, as I have no previous experience with these microcontrollers due to my mechanical background. Could you please suggest some reference or sample code I can take guidance from, for storing the data and later retrieving it from Portenta's RAM?  I really appreciate your help.I am currently using Arduino IDE for my sketch.

I don't know what Arduino ecosystem code is available. There are H7 ADC examples available in the STM32Cube IDE. The ADC will be what you want examples for.


text:
How to close/end a Wire.begin()?
I have an ESP32 cam, and I attached an i2c light sensor to it. I need to read the light level at startup, then I don't need the i2c connection again.
The problem is, the board uses 2 i2c connections I think (for the camera and such). So I use my custom pins for the sensor (15 and 16). It works well, I can read the light just fine, but then the camera fails because (I believe) the Wire.begin(15,16) changes the default pins and the camera gets confused.
So I would like to do something like Wire.end() to forget that I started the Wire.begin(). Any idea on how I can do that?
Here is the relevant code:
#define I2C_SDA 16
#define I2C_SCL 15
BH1750 lightMeter (0x23);
TwoWire I2Clightmeter= TwoWire(1);

void setup()
{
  I2Clightmeter.begin(I2C_SDA, I2C_SCL);
  lightMeter.begin(BH1750::ONE_TIME_HIGH_RES_MODE,0x23,&I2Clightmeter);

  delay(1000);
  uint16_t lux = lightMeter.readLightLevel();

//rest of the code

Have you tried Wire.end()?

Yes, of course. But there is no such function.

Looks like that's something Arduino overlooked. It's something we (optionally) implemented in chipKIT...  There is a way though, but it's not too fun.

This is the esp32 header for wire: https://github.com/espressif/arduino-esp32/blob/master/libraries/Wire/src/Wire.h If there is a way, I'd like to know it, because I can't use the camera without it :/

I just tried to reproduce this, but since I don't have a BH1750, I just ran the solution #1 from the answer below without anything attached and it does not crash for me. So maybe the bug is not in the wire library but in the lightmeter library (as it may register some interrupts). Try dynamically allocating that one as well.

Thanks for the effort. The program doesn't require a physical board, or even actually using the library. Just starting a  I2Clightmeter.begin(I2C_SDA, I2C_SCL); is enough to crash when the camera is initialized. However, I found a solution: moving SDA on pin 14 seems to work.

There is a way of doing it that's ESP32 specific. However it means changing how you define your I2C object.
The ESP32 system is set up so that if the TwoWire instance is destructed the I2C bus is released. But you can't do that with the way you normally define the object. So instead you have to use dynamic allocation to control it:
TwoWire *I2Clightmeter;

void setup() {
    I2Clightmeter = new TwoWire(1);
    I2Clightmeter->begin(I2C_SDA, I2C_SCL);
    lightMeter.begin(BH1750::ONE_TIME_HIGH_RES_MODE,0x23,I2Clightmeter);
    delay(1000);
    uint16_t lux = lightMeter.readLightLevel();
    delete I2Clightmeter;
    // rest of code
}

Another alternative is to keep the TwoWire object in a local scope so that it gets destroyed when you leave that scope - maybe with a special function for it:

uint16_t getLux() {
    TwoWire I2Clightmeter(1);
    I2Clightmeter.begin(I2C_SDA, I2C_SCL);
    lightMeter.begin(BH1750::ONE_TIME_HIGH_RES_MODE,0x23,&I2Clightmeter);
    delay(1000);
    return lightMeter.readLightLevel();
}

void setup() {
    uint16_t lux = getLux();
    // rest of code
}

Thanks, but unfortunately it doesn't work. If I put the delete there, it just boot loops. If I don't put the delete, it gives me the message as it did before: [W][esp32-hal-i2c.c:905] i2c_isr_handler_default(): eject raw=0x2, int=0x200

Did you try the second option? Localise it?

I didn't try it, but I don't see how it would work, since most likely once the function is called in c (on the esp32 specific code) it will set something that persists there until the device is rebooted or some other magic thing happens to reset it. Btw, the camera code does NOT use wire() in my program. It is used by the libraries in the backend. The only i2c code in my program is reading the light sensor.

It's worth trying. Give it a go and report back.

Another option is just to use the other i2c channel, and maybe other pins too.

Trying the first channel was one of the first things I tried. Unfortunately, it still crashed.

I tried the scope version, and, unsurprisingly, it got stuck in a bootloop too...

Hmm... then I am out of ideas at the moment, sorry. Maybe raise it as an issue on the github repo - it really shouldn't cause it to crash.

Thanks for your effort, I appreciate it. I asked on the esp32.com forum, if I don't get an answer there too I will open an issue on github as well.

Btw, from looking at the code, deleting the object should release the i2c. Unfortunately, something else is going on :/ TwoWire::~TwoWire()
{
flush();
if(i2c) {
i2cRelease(i2c);
i2c=NULL;
}
}

Yes, that's where I got the idea of destroying the object from. Maybe the problem isn't with the I2C - maybe the problem is with the camera code. I know you probably don't get much control over that though as it's mostly embedded in the core.

Ok, I solved the problem. I moved SDA on pin 14, and now it works, for some reason :D I believe it's still a bug with esp-32 cam, but at least I got it to work.


text:
two adafruit neopixel loops
i'm making a device that's kind of based on Russian roulette.
I have 5 LED's  that are normally  white, and when you press the button one of the LED's is marked red.
After some tinkering I figured out how to do this with  the help of adafruit neopixel, but i also want to have a RGB strip with a rainbow effect running on the same arduino at the same time (or only just before the button is pressed).
The problem is that it interferes with the activation and running of my  Russian roulette.
I know you can't run two loops at a time, but is there some kind of way to solve this?
I will put my code below, thanks in advance!
#include <Adafruit_NeoPixel.h>

const int buttonPin = 2;

int buttonState = 0;

#define LED_PIN  6

#define LED_COUNT 5

#define LED_PIN2  7

#define LED_COUNT2 60

Adafruit_NeoPixel strip(LED_COUNT, LED_PIN, NEO_GRB + NEO_KHZ800);
Adafruit_NeoPixel strip2(LED_COUNT2, LED_PIN2, NEO_RGBW + NEO_KHZ800);

uint32_t wit = strip.Color(255, 255, 255);
uint32_t wit2 = strip2.Color(255, 255, 255);

void setup() {

  randomSeed(analogRead(0));
  strip.begin();
  strip.show();
  strip.setBrightness(255);
  strip2.begin();
  strip2.show();
  strip2.setBrightness(255);
  pinMode(buttonPin, INPUT);

}

void loop() {
    rainbow(10);
    shotknop();
}

void shotknop (){
  buttonState = digitalRead(buttonPin);
    strip.fill(wit, 0, LED_COUNT);
    strip.show();
    if (buttonState == HIGH) {
    theaterChase(strip.Color(255, 255, 255), 150);
    shot(strip.Color(0, 255, 0), 100, 5000, 0);
    }
    else{
      }
}

void shot (uint32_t color, int wait1, int wait2, int rng) {
    strip.clear();
    rng = random(LED_COUNT);
    for(int a=0; a<15; a++) {
      strip.setPixelColor(rng, color);
      strip.show();
      delay(wait1);
      strip.setPixelColor(rng, (0, 0, 0));
      strip.show();
      delay(wait1);
  }
    strip.setPixelColor(rng, color);
    strip.show();
    delay(wait2);
}
void colorWipe(uint32_t color, int wait) {
  for(int i=0; i<strip.numPixels(); i++) {
    strip.setPixelColor(i, color);
    strip.show();
    delay(wait);
  }
}
void theaterChase(uint32_t color, int wait) {
  for(int a=0; a<10; a++) {
    for(int b=0; b<3; b++) {
      strip.clear();

      for(int c=b; c<strip.numPixels(); c += 3) {
        strip.setPixelColor(c, color);
      }
      strip.show();
      delay(wait);
    }
  }
}
void rainbow(int wait) {
  for(long firstPixelHue = 0; firstPixelHue < 5*65536; firstPixelHue += 256) {
    for(int i=0; i<strip2.numPixels(); i++) {
      int pixelHue = firstPixelHue + (i * 65536L / strip2.numPixels());
      strip2.setPixelColor(i, strip2.gamma32(strip2.ColorHSV(pixelHue)));
    }
    strip2.show();
    delay(wait);
  }
}

You should ditch every call to delay() in your code and learn how to use a non-blocking coding style involvingthe millis() function, just like in the BlinkWithoutDelay example. That will enable you to not do busy waiting, bit do multitasking by very rapidly switching between the two tasks. There are tons of tutorials about that on the web. Please look at some of them. Then - if it isn't clear - you can always come back here. Have fun with your projekt :-)

Yep, ditch all delay(). Daisy chain 2 loops so you have 1 big loop. Write a drawing function update 2 loops at one time following global array that stores colour info of all each single LED on both loops. Setup a timer to call your drawing function every ~40ms. In main loop(), do the fancy stuff by modify the global array (screen buffer). Also check for buttons and  stuffs there in main loop. Since you separate your logic code (in main loop) and visual code (run by timer), you can do delay() in main loop.


text:
RN42 Bluetooth HID KEYBOARD sketch by silverball
How can I use RN42 sketch by silverball
/*
  RN42_HIDRaw_Arduino.cpp - Roving Netowrks RN42 Bluetooth HID raw library
  Developed by Chris Leitner - 2012

  This library is free software; you can redistribute it and/or
  modify it under the terms of the GNU Lesser General Public
  License as published by the Free Software Foundation; either
  version 2.1 of the License, or (at your option) any later version.

  This library is distributed in the hope that it will be useful,
  but WITHOUT ANY WARRANTY; without even the implied warranty of
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  Lesser General Public License for more details.

  You should have received a copy of the GNU Lesser General Public
  License along with this library; if not, write to the Free Software
  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA

  RN42 HID raw report format:
  |start(1 byte)|length(1 byte)|descriptor(1 byte)|data(length - 1 [for the descriptor])
  Keyboard:
  |0xFD|9|1|modifier|0x00|code 1|code 2|code 3|code 4|code 5|code 6
  Keyboard modifier bits (sent as one byte)
  bit 7     |bit 6      |bit 5      |bit 4  |bit 3  |bit 2  |bit 1      |bit 0
  rt GUI    |rt alt     |rt shift   |rt ctrl|lt GUI |lt alt |lt shift   |lt ctrl

  You must initialize the Serial library in your code before you call any of these functions.
  The default speed for the RN42 is 115200 - add this in the setup function Serial.begin(115200);
  */

#include <stdlib.h>
#include <string.h>
#include <inttypes.h>

#include "RN42_HIDRaw_Arduino.h"

RN42_HIDRaw_Arduino::RN42_HIDRaw_Arduino(){
}

//Sends a raw report for a keyboard HID
void RN42_HIDRaw_Arduino::SendKeyboardRaw(char raw_data[], uint8_t mod_bit){

    //write the RN42 Keyboard raw header
    Serial.write((uint8_t)0xFD); //start byte indicator for RN42
    Serial.write((uint8_t)0x09); //length of the raw report (how many bytes)
    Serial.write((uint8_t)0x01); //descritptor byte see the RN42 HID manual for details 0x01 is keyboard
    Serial.write((uint8_t)mod_bit); //modifier bit (indicates shift, control, and other keys (see comments above)
    Serial.write((uint8_t)0x00); //unused always send 0x00
    //write the key press data
    //each of these should be an ASCII keycode indicating a keypressed
    //example 0x04 is an 'a' see the RN42 HID manual for a list of codes
    Serial.write((uint8_t)raw_data[0]);
    Serial.write((uint8_t)raw_data[1]);
    Serial.write((uint8_t)raw_data[2]);
    Serial.write((uint8_t)raw_data[3]);
    Serial.write((uint8_t)raw_data[4]);
    Serial.write((uint8_t)raw_data[5]);
}

//This function just send a raw report with no keys or modifiers pressed
void RN42_HIDRaw_Arduino::SendKeyboardRawBlank(void){

    //write the RN42 Keyboard raw header
    Serial.write((uint8_t)0xFD);
    Serial.write((uint8_t)0x09);
    Serial.write((uint8_t)0x01);
    Serial.write((uint8_t)0x00);
    Serial.write((uint8_t)0x00);
    //write the key press data
    Serial.write((uint8_t)0x00);
    Serial.write((uint8_t)0x00);
    Serial.write((uint8_t)0x00);
    Serial.write((uint8_t)0x00);
    Serial.write((uint8_t)0x00);
    Serial.write((uint8_t)0x00);
}

//Sends a raw report for a gamepad
void RN42_HIDRaw_Arduino::SendGamepadRaw(char x_left, char y_left, char z_pos, char rot_pos, uint8_t buttons1, uint8_t buttons2)
{
    //write the header part for RN42
    Serial.write((uint8_t)0xFD); //start byte
    Serial.write((uint8_t)0x06); //length of the descriptor
    //gampad positions and buttons
    //on a gamepad there typically is two analog joysticks one is typically used to
    //indicate x/y position and one is for z/rotation.
    Serial.write((uint8_t)x_left); //value between -127 to 127 indicating the x postition
    Serial.write((uint8_t)y_left); //value between -127 to 127 indicating the y postition
    Serial.write((uint8_t)z_pos); //value between -127 to 127 indicating the z postition
    Serial.write((uint8_t)rot_pos); //value between -127 to 127 indicating the rotation postition
    //one bit for each button pressed there can be a total of 16 buttons one byte in each
    //set the bit to show a button pressed and clear the bit to indicate not pressed
    Serial.write((uint8_t)buttons1);
    Serial.write((uint8_t)buttons2);
}

void RN42_HIDRaw_Arduino::SendMouseRaw(uint8_t buttons, uint8_t x_stop, uint8_t y_stop, uint8_t wheel){
    //write the header part for RN42
    Serial.write((uint8_t)0xFD);
    Serial.write((uint8_t)0x05);
    Serial.write((uint8_t)0x02);
    //gampad positions and buttons
    Serial.write((uint8_t)buttons);
    Serial.write((uint8_t)x_stop);
    Serial.write((uint8_t)y_stop);
    Serial.write((uint8_t)wheel);
}

And act Like Keyboard.h do ? just simply putting keyboard.press;
JUst noob question.

I think you're going to have to be more specific.

You see when you  put on your code this sample keyboard.press(KEY_LEFT_ARROW) it actually does that key on keyboard. But you cant do that if you're using Bluetooth module (unless your using ESP32). Im using RN42 and i want to do the same function as keyboard.h does. Ive been searching for 2 weeks and i stumbled upon that sketch above saying that it is keyboard sketch for RN42. But i dont know how it actually put on my sketch like keyboard.h does.

are you saying that you want to use the RN42 as a USB keyboard?

no, what i'm saying is, I want it to act as keyboard. I know its RN42 cant act as USB Keyboard thats why im searching for BLE Keyboard sketch. And silverball says that this code can act as keyboard
https://stackoverflow.com/questions/16243602/arduino-rn-42-bluetooth-module-hid
He says in this question. But didnt say how to use it. Im begginer at arduino and Im connecting RN42 to my Arduino Pro Mini. I want the RN42 to send a data that read in computer like you press a keyboard.

if you are using an Arduino, I recommend you to use the BPlib, it's a free arduino library that contains functions that are similar to the Keyboard.h.
The following link is from the Arduino website: https://www.arduino.cc/reference/en/libraries/bplib/
When you download the Lib, take a look at the examples given by the creator of the Library, all the example code have the explanation of each funcition used, and you can also check for some documentation online. I hope that this help you!


text:
Switch on the piezo emitter for a short time
I need a short beep for every minute of change. I wrote a separate function. The signal duration should be 50 ms, the rest of the time the emitter connected to the A1 contact should be silent.
A really working sketch is shown below:
uint32_t mysound; // Variable for storing time (duration of the sound signal)
uint32_t myTimer1;
uint32_t t; //Time that always increases
byte seconds; // Seconds
byte minutes; // Minutes
int k = 1;
void setup()
{
  DDRC = B00000010; // Set pin A1 as output
  //      76543210
  Serial.begin(9600);
  myTimer1 = millis();
}

void loop()
{
  t = (millis() - myTimer1) / 1000; // Time in seconds
  seconds = t % 60; // when 60 seconds are reached, it is reset to zero
  minutes = t / 60 % 60; // Counts the minutes and drops to zero when 60 minutes are reached
  Serial.println(seconds);
  if (seconds == 0 && k)
  {
    sound();
  }
  if (seconds > 0) k = 1;
}

void sound()
{
  mysound = millis();
  while (millis() - mysound < 50)
  {
    PORTC = B00000010; // We set high voltage on pin A1 for a time of 50 ms
  }
  k = 0;
  PORTC = B00000000;
}

doesn't work is a meaningless description of what you observed ... please describe what happens ... also, describe what tests you performed to make sure that the piezo emitter works

does the piezo make sound with pin HIGH?

Yes, if you just raise the pin to a high level, then the piezo emitter beeps

All my attempts end with him either constantly beeping or constantly silent. I was unable to achieve a short-term peak

I assume, you are using atmega328 or atmega2560 when using register PORTC instead of digitalWrite() for generic arduino board. Are you trying to avoid using TIM1 or TIM2? And so maybe there is a reason to avoid using delay() as well. So try this one single line code >>>>  if ((millis() % 60000) < 50) PORTC |= 0x02; else PORTC &= ~0x02;

Your myTimer1 in t = (millis() - myTimer1) / 1000; is not set

In addition to Qareke's answer, you also have a problem with the mysound variable. You only set this timestamp to millis() inside your millis() if statement. mysound is global and thus will be implicitly initialized with zero. So, by the time, that the code reaches the if statement, the difference between millis() and mysound is most likely already too big, thus the timestamp gets never set.
Solution: You need to move 2 lines around in your code:

Move the mysound = millis(); statement up into the if (seconds == 0) statement.
Move the sound(); statement outside of the if statement directly into the void loop() function (for example directly after the if (seconds == 0) statement).

Now the sound() function will always be executed, but it will only do a sound, if the timestamp was set to millis() previously, and then only for 50ms. Now we only need to make sure, that the timestamp variable mysound will only be set once, when the seconds get zero. You could either introduce a new flag variable for that, or you could just use the timestamp itself and check, if more than 1s passed since the last time the timestamp was set. So you need to change
if (seconds == 0)

to
if (seconds == 0 && millis() - mysound > 1100)

I used 1100 (1.1s) here, to make sure, that there is no bad edge case happening. Since seconds will only get zero every minute, that shouldn't be a problem.

Sorry, but I did not understand how you can move a function call out of a condition. Then what remains within the condition?
I fixed the program from above, in this form the squeak starts but never stops

If you read my answer closely, you see, that I instructed you to move the mysound = millis(); statement inside that if statement. But you have put still inside the sound() function. Also you have chosen to use a flag variable (instead of the proposed millis() solution). So you haven't used my solution to the problem. Nonetheless, your current code works perfectly for me. I don't have a piezo at hand, but my logic analyser shows a 50ms long positive pulse every minute. If that doesn't work for you, probably there is something wrong with your wiring


text:
Aurdino EMG sensors and servos?
I'm new here and to the aurdino.
I'm building a 3D printed robotic arm controlled by a EMG sensor. I purchased a V3 EMG board and leads on Aliexpress. Here's a list of the things I've purchase for this project

Arduino Uno

EMG sensor

2 MG996R servos 7.2 max voltage I know not to power these through the
board.

X4 AA battery pack with male barrel input lead to power the arduino.
Wiring, header pins and cables.

I don't have any breadboards BTW.
The functionality is basic, servos on pulleys and strings, I'm looking for one servo to control the open close hand function, and the other is to open and close the index and thumb for a pinch function to pick up smaller objects.
I need to know the following,
Option to power servo, EMG sensor and arduino from single power source or two batteries and how to wire these a simple picture or schematic would be great.
What code can I quickly copy and paste to perform the functions I mentioned.
I do have some very basic DC electronic experience.
I just don't want to damage my components by just experimenting as it takes weeks to replace them otherwise.  Thanks.

What is the question?

"What code can I quickly copy and paste to preform the functions I mentioned." - Most likely you won't find a code online, that does exactly, what you want (and we are not a googling machine to search for them). So you will most likely need to write that code yourself. Yes, that will take a while, but you can look at tutorials for each individual part of the project, understand them, and then use that code and understanding for your project. When you have each individual part working, you can put all these things together in one code.

On Arduino Projecthub you can find a lot of tutorials about robotic arms. I don't know what EMG sensor you own, but here is an tutorial.

Your question is like asking for source code and schematic for a prosthetic arm that could be in a million dollar commercial project. I guess there are a few people sharing their work on the internet, but I doubt there is one that you can just, here I quote your words, "quickly copy and paste to perform the functions I mentioned"


text:
I2C_anything from Nick Gammon. Value of two senders to be received and printed by receiverslave
Following the suggestion of Fiendish to post here:
Hello
Nick, thank you very much for this I2C-anything library that works a treat with two arduinos (one sender, one receiver).
Is there any suggested method or at least an example sketch of having two different sender arduinos send their floats to the receiver  e.g. by alternating slave adresses in the receiver loop? With a simple re-insertion of the section (but with a different address) into the receiver sketch restarting with Wire.begin() and then Wire.begin(new address) things are botched up.
In addition: if I define -float f in sender A- and -float e in sender B- the receiver keeps on printing the float e value in the serial.Print ("float value e"); serial.println(e); -postion, no matter if I swap from Sender A to sender B -by changing the SCL/SDA connections,  and the serial.Print ("float value f");serial.println(f); prints fancy numbers.
If at least the swapping would cause the floats to be printed in the correct position I could maybe switch the respecive senders I2C down in turns....
Of course hotplugging /hotswitching SDA and SCL from senders causes the senders sketch to be blocked at times.
The idea of sending data from Sender B to Sender A, and from Sender A to to receiver left me frustrated the last few hours, due to the fact that Im a total noob and/or that its simply not possible to have two masters send to one slavereciver without running into i2C conflicts. Unless some unknown acrobatics is performed.
The ultimate idea is to have two separate megas (with i2c sensors attached to them) execute feedbackloops and still be able to transfer these values and other values to a display via I2C. the alternate way could be that a dac is used to translate the I2C values into voltages that hardware....)
Any help greatly appreciated
Best
Daniel

Please draw a schematic for us. It is not really clear to me, how the setup is and why. Also please show your code. Without these two, your description is really difficult to understand. Generally I would discourage the use of multi-master mode in I2C. I'm myself working on multi-master for ATtinys, and I have to say, that it can be a real mess. If you describe the context, maybe we can point you to a better alternative.

Please describe why you think you need multiple masters for one slave. As chrisl wrote, I2C multimaster typucally is not much fun and there might be simpler solutions (one master/ 2slaves, I2C combined with UART, etc.)

Dear Chrisl and Sim Son
Please accept my apologies for not replying earlier, am still recovering form a timbering accident and have limited painless access to my laptop.
thinking in boxes: BOX 1 = Arduino Mega number one regulates the pressure of proportional valves (via I2C conected quaddac MCP4728 to 0-10V) based on the flowvalues of 4 I2C-connected FLowsensors.
BOX 2= Arduino Mega number two does the same with a second set of 4 flowsensors and 4 analog proportional valves.
Splitting this to two arduinos was originally because a) i was unable figure out how to get 2 DACS on the same I2C line and handle the LDAC address fiddling which turned out to be a good approach because the total number of required GPIO pins exceeds the available number of pins of one Mega (many rotary encoders attached, TTL signal delayer for 8 channels, pots to set values, status LEDS.
Both arduinos are supposed to send the values for the flow-setpoints, actual pressure values, actual flow values, other sensor data to a third arduino MEGA =BOX 3 that displays all kind of things on a large TFT. (for what its worth, this third Mega has some inputs from a different set of other I2C sensors that basically provide TTL signal outputs, if event-criteria have been met. the latter TTL are fed back to the first two arduinos to provide decision criteria in if loops)
So, i learn from you that the multimaster approach unlikely to be fun at all, especially given my limited knowledge and loathing /ignorance to handle and send strings. You will at least laugh at me now but i saved quite some time the on day i wrote to you by simply translating all the flow etc values of BOX 1, Box 2-Ardinos (pressures, flowsetpoints and actual flow values into voltages with the help of additional multiplexed DACs, then I pick up the the voltages with I2C-ADCs hooked to the Arduino with the SPI-display (BOX 3) that in turns translates into the true values and prints to the TFT. Any delay and inprecision at the displays side is acceptable so far, analog value fluctuation has been smoothed, the additional hardware is no issue at this stage of the project.
I am sorry that his original issue regarding I2C led me astray to oldfashioned analog data processing
BUT: if you have any hints or pointers to libraries as how two arduinos that act already as I2C Masters can send their data (a bundle of floats) via UART/RXTX, or any other bus to a receiver that handles these as printable variables: more than welcome, i will try to keep abreast of what you suggest.
Best
Daniel


text:
Firmata: strings sent from the computer become damaged after Arduino
I have a Python program that acts as a Firmata client. This program connects to the Arduino at a user-specified COM-port (with Firmata onboard, the sketch can be seen below), sends the user-requested string message to the Arduino, and awaits Arduino's reply. If the reply is present, the program prints it out as a list of ASCII symbol codes.
I expect the program and the sketch to work this way (block scheme is below), but the strings coming from the Arduino are damaged. They don't contain all symbols which were sent, but they contain only the first symbols in some random order, with a \0 symbol present after each character in the string. For example,

String sent to the Arduino
Received as ASCII symbol codes
Received as a string

A
(65, 0)
A\0

AB
(65, 0) where is the B?
A\0

ABC
(65, 0, 67, 0) the B lacks presence
A\0C\0

ABCD
(65, 0, 67, 0) the received data length remains the same, but B and D aren't present
A\0C\0

ABCD(10)
(65, 0, 67, 0, 40, 1, 48, 1) WHAT IS THIS?
A\0C\0(\10\1

DHTt(4)
(68, 0, 84, 0, 40, 0, 41, 1)
D\0T\0(\0)\1

Program's screenshot:

Awaited work algorithm block scheme:

Python program code:
import pyfirmata, time

class CustomArduino(pyfirmata.Arduino):
    def __init__(self, port: str):
        pyfirmata.Arduino.__init__(self, port)
        self.iterator = pyfirmata.util.Iterator(self)
        self.iterator.start()

        self.add_cmd_handler(0x71, self.receiveString)

    def receiveString(self, *args, **kwargs):
        print(f'Received: {args}')

    def sendString(self, data):
        self.send_sysex(0x71, bytearray(data, 'utf-8'))

    def send_sysex(self, sysex_cmd, data=[]):
        """
        Sends a SysEx msg.
        :arg sysex_cmd: A sysex command byte
        : arg data: a bytearray of 7-bit bytes of arbitrary data
        """
        msg = bytearray([pyfirmata.pyfirmata.START_SYSEX, sysex_cmd])
        msg.extend(data)
        msg.append(pyfirmata.pyfirmata.END_SYSEX)
        self.sp.write(msg)

print('STRING TESTER\nPlease input your COM port: ', end = '')
myCom = str(input())
device = CustomArduino(myCom)

while True:
    device.sendString(input('Send: '))
    time.sleep(1)

Arduino sketch:
#include <Firmata.h>

void stringCallback(char *myString)
{
  //The function accepts one charset.
  Firmata.sendString(myString); //send the *same* charset  back
}

void sysexCallback(byte command, byte argc, byte *argv)
{
  Firmata.sendSysex(command, argc, argv);
}

void setup()
{
  Firmata.setFirmwareVersion(FIRMATA_FIRMWARE_MAJOR_VERSION, FIRMATA_FIRMWARE_MINOR_VERSION);
  Firmata.attach(STRING_DATA, stringCallback); //when there is a STRING incoming to the Arduino, call 'stringCallback'
  Firmata.attach(START_SYSEX, sysexCallback);
  Firmata.begin(57600);
  pinMode(13, OUTPUT);
}

void loop()
{
  while (Firmata.available()) {
    Firmata.processInput();
  }
}

How I can deal with this?

Firmata doesn't normally do something with a string (the commands are binary), so what do you want the arduino to do, actually? What you see (and why there are so many 0's in the reply) is that Firmata encodes texts, both on sending and on receiving.

@PMF, the \0s insertion wouldn't be a problem if the string returned by the Arduino contained all the characters present in the string. However, alongside with \0s insertion, not every single character present in the sent string exists in the received string.

@PMF, edited my question to make it answer your comment.

Instead of using the UTF-8 encoding,
def receiveString(self, *args, **kwargs):
    print(f'Received: {args}')

def sendString(self, data):
    self.send_sysex(0x71, bytearray(data, 'utf-8'))

it is necessary to use the pyfirmata special bytearray manipulation methods: two_byte_iter_to_str and  str_to_two_byte_iter:
def receiveString(self, *args, **kwargs):
    print(f'Received: {pyfirmata.util.two_byte_iter_to_str(args)}')

def sendString(self, data):
    self.send_sysex(0x71, pyfirmata.util.str_to_two_byte_iter(data))

You have to understand the Firmata protocol to write your own client library. The spec is here: https://github.com/firmata/protocol.
In this particular case, you need to know that data that is sent (the string in this case) can never use bit 7 of the data, since these values have special meanings. Therefore, Firmata sends every byte as two bytes, first bits 0-6 and second bit 7 as bit 0 of the next byte. Therefore, the conversion to UTF-8 is not sufficient. You need to do a two-byte-per-8-bits encoding. The same applies for the reply.

The pyfirmata client library is alright, considering that any library is going to be bad in case of its misuse, just as in my situation. In my case, the problem was on the Python program's side

Alternatively, if you want a system without Firmata's baggage of ancient MIDI constraints, like its bizarre 7-bit limit, you might consider DaqPort https://www.daqarta.com/dw_rraa.htm

your option is too hard to study in.


text:
Arduino Due Serial Port Not Showing - Mac
Using a Mac (Big Sur 11.1)
When trying to set up the IDE I was able to install the package that contained the Due board, but the serial port for my Arduino Due isn't appearing in Tools -> Port -> Serial Ports. I did some searching and it seems that other Mac users had this problem as well.
If anyone has any tips on how to get my computer to recognize and show the serial port I'd appreciate it. I'm just getting started with these.

If your Due has an FTDI transceiver on it I'm curious to see a picture of it.  The only Due clones that I've seen, like the original, use at ATMega16u2 for the transceiver chip, in which case the FTDI drivers play no role.

Yeah that was a misstep in my end. I was just trying different things until I learned that. Now I’m wondering if it’s an issue with the OS.

It is probably best to remove that from the question then, because it just creates a rabbit hole.

Do you have anything at all attached to the board besides the USB cable?

Good suggestion. I removed it and no only the USB

It's been a while since I had much contacts with macs, but there should be a "device manager" of some sort.  USB device will list in it even if there are no drivers, wrong, drivers, etc.  You can edit into your question information regarding whatever shows up in there, or if nothing shows up at all.  Make sure you're focused on the "programming" port, since that gives the greatest chance of success.


text:
Computer freezes while collecting serial data from Arduino Uno
I am an arduino noob. I have been searching for some interesting arduino projects recently and making a game controller using Arduino UNO seemed interesting. So I hooked up two dual-axis joystick modules to the arduino board and wrote a program to print something corresponding to the joystic movements. I collected the serial data through USB and passed it on to a python program. The code works fine, mostly. But the problem is, when I hook up the circuit and start using the joysticks, after few minutes my system  is freezing.
Why is my system freezing?
What can I do to avoid the freezing?
My system info:
1.Windows 10 64-bit
2.4GB RAM and 512GB HDD
Here is the code
int SW = 9;    // mouse joystick
int xpin = A0;
int ypin = A1;
int SW1 = 6;  //movement joystick
int xpin1 = A2;
int ypin1 = A3;
void setup()
{
  Serial.begin(9600);
  pinMode(SW, INPUT);
  digitalWrite(SW, HIGH);
  pinMode(SW1, INPUT);
  digitalWrite(SW1,HIGH);

}
int prev_state = 0; // previous state of switch
void loop() {
  int z = 0, xpos = 0, ypos = 0;
  int z1 = 0;char xpos1='0', ypos1='0';
  int x = analogRead(xpin);
  int x1 = analogRead(xpin1);
  int y = analogRead(ypin);
  int y1 = analogRead(ypin1);
  int sensitivity = 15; //mouse sensitivity

  if (x >= 550)                  // when moved up
    xpos = map(x, 550, 1023, 0, sensitivity);
  if (x <= 450)                // when moved down
    xpos = map(x, 450, 0, 0, -sensitivity);
  if (y >= 550)                 // when moved right
    ypos = map(y, 550, 1023, 0, sensitivity);
  if (y <= 450)               // when moved left
    ypos = map(y, 450, 0, 0, -sensitivity);
  int curr_state = digitalRead(SW);
  if (curr_state == 1 && prev_state == 0) // when SW is pressed
    z = 1;
  else
    z = 0;
  int prev_state1 = 0;
  if (x1 >= 550)                  // when pressed d
    xpos1 ='d';
  if (x1 <= 450)                // when pressed a
    xpos1 ='a';
  if (y1 >= 550)                 // when pressed w
    ypos1 ='w';
  if (y1 <= 450)               // when pressed s
    ypos1 ='s';
  int curr_state1 = digitalRead(SW1);
  if (curr_state1 == 1 && prev_state1 == 0) // when SW1 is pressed
    z1 = 1;
  else
    z1 = 0;
  if (xpos != 0 or ypos != 0 or z == 1 or xpos1=='d' or xpos1=='a' or ypos1=='w' or ypos1=='s' or z1 == 1) // prints when the joysticks are moved
  {
    Serial.print(xpos);
    Serial.print(":");
    Serial.print(ypos);
    Serial.print(":");
    Serial.print(z);
    Serial.print(":");
    Serial.print(xpos1);    // prints the data and separating by ":"
    Serial.print(":");
    Serial.print(ypos1);
    Serial.print(":");
    Serial.println(z1);
  }

  prev_state = curr_state;
  prev_state1 = curr_state1;
   delay(10);
}

I am using a python program, in visual studio code, to read the arduino serial data and perform the required operation.
The python code
import mouse, sys
import time
import serial
import keyboard as kb

mouse.FAILSAFE=False
ArduinoSerial=serial.Serial('com3',9600)  #assigning com port
time.sleep(1)

while 1:
      data=str(ArduinoSerial.readline().decode('ascii'))   #read the data
      (x,y,z,x1,y1,z1)=data.split(":")           # assigns to x,y,z,x1,y1,z1
      (X,Y)=mouse.get_position()        #read the current position of mouse cursor
      (x,y)=(int(x),int(y))
      mouse.move(X+x,Y-y)           # move camera/mouse
      # press the desired keys corresponding to joystick movement
      if y1=='w':
         kb.press('w')
         kb.release('w')
      if y1=='s':
         kb.press('s')
         kb.release('s')
      if x1=='a':
         kb.press('a')
         kb.release('a')
      if x1=='d':
         kb.press('d')
         kb.release('d')
      if '1' in z:                        # read the Status of SW
         mouse.click(button="left")    # clicks left button
      if '1' in z1:                    #read SW1
         kb.press('space')             # press space

To be clear, your system is freezing to the point where you need to power cycle the PC?

Even though the communication only runs at 9600, I suspect that's just to many keyboard presses you're generating here. If, for instance, you move left, it will generate around 9000 presses of the "a" button. No human would ever be able to do that.


text:
Reading I2C registers as slave device
I need to read the registers of a message gotten from onReceive(). I read here that

There's nothing "magic" about the register pointer:  it's simply the first data byte in the packet.  So just write your I2C slave code so it examines the first received byte and treats it as an "opcode" for deciding how to interpret the rest of the packet.

So I thought that since hosts set registers by calling write() twice, I could just make my onReceive() handler function twice, like this
byte CURRENT_REGISTER = 0x00;

void onMessage(int numBytes){
  if(CURRENT_REGISTER == 0x00 && numBytes == 1){
    CURRENT_REGISTER = Wire.read();
    return;
  }

  char msg[numBytes];
  for(int i = 0; i < numBytes; i++){
    msg[i] = Wire.read();
  }

  //logic function goes here

  CURRENT_REGISTER = 0x00;
}

But then i noticed here that

This first byte written here 'r' moves the register pointer to the register with address 'r'. You can think of the pointer as a read/write head.
Now that the pointer is 'pointing' at the specific register you wanted, this command will replace the byte stored in that register with the value 'v'.

which made me think after endTransmission(), it only sent one message, which would ruin this idea.
Is this the case, and if so how can I obtain the registers as a slave?

You reallly should provide more context. What are you trying to achieve? About was registers are you talking?

@chrisl i was trying to provide a minimal example, since the context is alot. But if you want to know, im trying to replace a wiimotion+ IMU with a BNO055, and i need to communicate to the wimmote over an I2C connection in a specific format to be understood. There are specific registers a wiimote expects that when it writes to it receives a specific response back, and im trying to emulate these responses with an arduino nano. I need to know the register in order to know how to respond. If you need more context, look at this link wiibrew.org/wiki/Wiimote/Extension_Controllers#Wii_Motion_Plus

The forum threats, that you linked to, are totally unrelated to the wiimote. The only common thing is, that - like many other devices too - the wiimote seems to read its peripherals by first sending a "register address" in the peripheral device (the address of the sensor internal memory), that it then wants to read or write. From what you linked in the comments, for the wiimote, that "register address" doesn't really correspond to a register. It is more like a command, that is send by the master.

So you need to first actually understand the communication protocol, that the wiimote uses. Then you can start implementing it. From your link it seems, that there is first an initialization process. Also something about possible encryption. The site isn't easy to understand.

@chrisl okay so, the wiimote communicates over i2c. these registers in fact do matter, and wiimotion plus is unencrypted, but even if it was, im initializing it in a way which encryption does not matter. Not only is this incorrect, but this has even been done before the opposite way around, with the arduino nano as the master and wiimotion+ as the slave.

I didn't say, that registers wouldn`t matter, just that they might be better interpreted as commands here, as they don't seem to correspond to physical adresses in a memory stack. And I know, that this has been done before. I just wanted to make clear, that you cannot necessarily copy the communication principles of other chips to this one. Currently it is unclear, what exactly your question is. Thus I guessed, that there might me some fundamental misunderstanding. Please elaborate more on what you have already done and where exactly your problem lies

@chrisl Games which utilize the wii motion plus depend on specific commands or registers, whatever you want to call them, to respond accordingly or the game will crash. I know what the responses would be, but i don't know how to determine what register/command is being asked of. This is why i am asking "how to Read I2C registers as slave device".

An I2C slave does never read any registers, only the master can initiate bus transactions. A slave can only be written to and it has no control over what it receives. I beliebe you have some misunderstanding about I2C which makes it hard to understand what you're asking.

I just realized, what your actual question might be, so I'm prepending this to my answer:
With I2C and the typical register communication protocol, you have 3 communication patters:

Master wants to write:

Master does transmission with first byte being the address of the register and following bytes being the data, that should be written to the addressed register (and following registers)

Master wants to read:

Master does a 1 byte transmission with the address of the register, that is wants to read
Master starts a request for 1 or more bytes and the slave will send the previously requested register (and following registers, until no more bytes are available or requested)

Some devices have sequential reads. For these devices the register address is not reset, when an operation is done. Thus the master could do more requests and read more data from the registers. Here the current register address is incremented on each read.

This means, that a master write cycle has only 1 transmission (only 1 endTransmission() in the master code), since every first byte in a master send transmission is handled as a register address. Your code snippet does not allow that. To solve that, just remove the check of numBytes and the return statement.

As mentioned in the comments, your question is really unclear. It seems you are asking things, that doesn't really make sense in the context of general I2C communication. So I will go over the basics and then point you in a good direction to solve your problem interfacing the Wiimote as peripheral.
The I2C protocol: This is the general communication protocol, that the Wiimote uses for its peripherals. It uses 2 lines and a master-slave structure. That means, that any communication is controlled by the master (the Wiimote in this case) and the slave (the peripheral, like a Motion+, a Nunchuk or your Arduino) cannot do anything by itself. The I2C protocol has markers for the start and end of a message and can address each slave on the bus with its specific address (which is send before the data). The protocol does NOT include any rules about the content of each message. So when writing code with the Wire library (the Arduinos library for interfacing the I2C hardware), you only get a buffer full of data bytes. It is up to you to interpret these bytes as needed for your application.
Data structure protocol: This protocol is imposed onto the data, that is end via I2C, so this is a higher level of abstraction and does not really have much to do with the I2C interface (you could use this data structure protocol with any binary communication interface, that has the concept of separated data packages). The data structure protocol defines the logic of the communication.
Here the registers come in. I2C is often used to interface simple sensor chips. These chips work by reading and writing to their internal memory. So the I2C interface exposes this internal memory to the master, who can now configure the sensor by writing data to the internal memory of the sensor, or read data from it.
An example: Lets imagine a simple distance sensor. It has 2 bytes/registers of internal memory. The first byte/register is for configuration of the sensor; the second byte/register represents the measured distance. The common communication protocol for such a chip can be:
Master sends the address of the register, that it wants to access
if Master wants to write to the register
    Master sends bytes to the slave
    Slave saves bytes into previously chosen register (and following registers)
if masters wants to read form the register
    Master requests X bytes from the slave
    Slave sends X bytes with the content of the previously chosen register (and following registers)

The I2C master now wants to configure the sensor (for example setting the measurement frequency), thus writing a corresponding byte to the first byte/register. It will first send the address of the configuration register to the slave, which is 0 (first byte/register). Then it will send another byte, which is the new value of the configuration register.
Then our I2C master wants to read the distance measurement the sensor. For this it first sends the address of the register, that holds the distance measurement (1 aka second byte/register). Then it will request 1 byte from the slave. The slave will then send the content of the previously chosen register (register 1 aka distance measurement register).
So for the slave, the first byte of a Master send transmission is to be handled as a register address. More complex slave classes might have a 16bit (2byte) register address or even more.

Now to your problem mimicking a Wii Motion+. The description on the site, that you linked to is rather difficult. Unfortunately I cannot help much with that. But you can try to use an already existing library, that mimics a Wiimote peripheral: Arduino-Wiimote
I cannot guarantee, that is will work, but it is definitely a good start. If you don't want to use a library, but implement this yourself, you can still learn from how the library does it.
With more searching (for term combinations like "github wiimote arduino") you might find more libraries for this. I have only invested a limited amount of time.


text:
Blink only one led in a led strip
I wish to blink only one led (number two in the strip) bit it does not do so, any idea why and how can I do it?
Code:
#include "FastLED.h"

//Number of LEDs
#define NUM_LEDS 9

//Define our clock and data lines
#define DATA_PIN 11
#define CLOCK_PIN 13

//Create the LED array
CRGB leds[NUM_LEDS];

void setup() {
      FastLED.addLeds<APA102, DATA_PIN, CLOCK_PIN, BGR>(leds, NUM_LEDS);
      FastLED.setBrightness(5);
}

void loop() {
  leds[0] = CRGB::Blue;
  leds[1] = CRGB::Green;

  //Blink this one only
  leds[2] = CRGB::Red;
  leds[2] = CRGB::Black;
  delay(500);
  leds[2] = CRGB::Red;

  leds[3] = CRGB::White;
  leds[4] = CRGB::Purple;
  leds[5] = CRGB::Green;
  leds[6] = CRGB::Blue;
  leds[7] = CRGB::Yellow;
  leds[8] = CRGB::Red;
  FastLED.show();
}

does not do so does not describe what it does ... please describe what you expect to happen, and what you observe happening

Let me translate that for you. The OP want the 2nd LED blink while other LEDs stay the same, but the code he wrote didn't do that. He didn't know how to code and wanted to learn from some experience guy how to do that. Is that clear enough?

Everytime, that you want the LEDs to change, you need to call the FastLED.show() function. You are doing that only once after you set the values multiple times. Also you need 2 delays in total (1 for the LED being on, 1 for it being off).
The workflow for blinking an LED would be:
Set LED to on
Call show function
Delay
Set LED to off
Call show function
Delay

You need to translate that to code.


text:
Part of Board exploded when Peltier Plate was wired t(o Board
Photos and Screenshots: https://i.stack.imgur.com/NazA6.jpg
By the way, I used a screenshot that was originally from this post: Have I bricked my Arduino Uno? Problems with uploading to board
Hey guys,
I was trying to wire two TEC1-12706 Peltier plates to my breadboard, and I saw that using the USB connection for power was not enough for both plates. So, I found a 19v--3.9A DC/AC adapter/computer charger and plugged it in to my Uno via the Power Jack port. The Peltier plates were not wired to the board when I plugged it in and everything looked fine, all the normal LEDs on the UNO lit up, etc. Then, I wired a peltier plate to my breadboard. As soon as I did, a part exploded, and grey smoke come out of the "L" light area. I unplugged it immediately. The next day, I plugged the adapter back into the Power Jack port and a screenshot is attached of some observations I made by touching the board. Photos of my Uno are also attached. As you can see, the "Slightly less hot but still burning part" is pretty much destroyed. The "L" light will not light up and as of right now I can't upload any code to it. Might be an unrelated issue so I will continue troubleshooting that, but it is still another observation. The test LED I wired is lit up, so I guess the board can still kinda function? I'm high school student and obviously a complete beginner. Will continue to do research on this. I really want to know what happened. Please help?  Thanks everyone.

Certainly you've blown your 3.3V regulator - probably by blowing the 5V regulator and pumping 19V straight into the 5V section of the board. It's toast.

You did a pretty good job of nuking your board. Gratz.
Basically what has happened: you connected 19V to the input of the 5V regulator (rated at 800mA max) and connected a 12V 50W device to the output.
I have no idea what a peltier will do when under powered, but at 12V it's going to want about 4A. That's 20x more than the 5V regulator can provide (also exacerbated by the massive amount of heat needed to be dissipated to drop 14V) - so it went pop.
In going pop it short circuited. That meant that 19V (or just short of) ended up going into the rest of your Arduino. The 3.3V regulator didn't like that (the bit that looks toasted), and neither will any of the rest of the components on the board.
In short: probably almost every component on the board has been nuked.
The moral of this story: don't connect high powered 12V devices direct to the Arduino. Things like peltier devices need their own dedicated power supply which can be controlled (as you would a motor or relay) through a power MOSFET.

Thanks so much man! This makes alot of sense. You think there's any way of salvaging the board? Appreciate your response.

There is no financial benefit to trying to fix it. The only benefit would be that you know how to fix it. If you fancy learning about component level diagnostics and testing then this could be a fun project. If you just want a working Arduino as cheap and easily as you can, then buy a new one.

Definately will be a Spring Break project for me when I'm finished school. Again, thanks man!

Quick question- if the regulator can supply 800mA and the peltier needed 4A, wouldn't the peltier just been underpowered and nothing happens?

Not with 19v going into the regulator. Yes it would be under powered for a while, until the regulator melted...

The regulator on your Arduino board is Linear regulator. Meaning it translates "excessive voltage" into heat. The analogy is, you need 5v out of 19v, you waste 17v. Even at 800mA, the amount of energy turned into heat is pretty much 17v * 800mA = 13.6w. Imagine how hot it would be if you compare that same amount of energy you pump into the core of 12v - 10w halogen light bulb. Yep so hot that metal wire turns into bright yellow light.


text:
4 Pelteir Plate Water Bottle wired to Arduino Uno
Note - I plan to use the Arduino Starter kit to make this project.
Hey everyone,
I've had an idea for a project recently and I would like to get some insight on its plausibility. Is it possible to heat and cool a bottle of water using 4 pelteir plates? I'd like to heat up or cool a bottle of water using 2 pelteirs for heating and 2 for cooling. Could the amount of power for the peltiers to function be supplied from a laptop, computer, or battery pack? The role of the Arduino is to program in some safety features or some things to help the circuit function better if necessary. For example, a feature I want to add in is if the cold pelteirs are on, the hot peltiers are off if nessecary. I might add an LCD to display which setting is on/off if I can (example: Cold: ON, Hot: OFF)
Thanks guys.

your question is not about arduino ... it is about supplying power to a peltier cell, so it is off topic here

From the positions of Arduino beginner it is unlikely for a beginner to be fully aware of where arduino ends. As this is a forum is targeting area for beginners and many people start with idea of switches, currents (rather then watts) with arduino, you cant expect standard of question on a leave of main stack-exchange...

You need a second power source, different than the laptop (USB provides up to 500mA in standard config, not enough for serious cooling)

There are no "heating" or "cooling" peltier elements. If you change the polarity of the power source, the hot and cold side changes too. The peltier element pumps the warmth from one side to the other. The temperature difference can not be more than 70 K. If one side gets cold the other gets hot and vice versa. Did you think of that, when you designed the water bottle. Also, peltiers are not very effective. You waste a lot of energy. So, I think too, you need a better power supply then a usb port ;-).

Yeah, I understand that, didn't word very well in my post. Thanks!

When it comes for amount of power from laptop, then this is not realy reasonable to expect even USB3, maybe some older laptops PCMCIA, or hardware docks. When it comes to Desk, They would have to be adjusted to get the ATX from PSU (it would have to be upgraded for purpose) We are still talking about a small Can or Yacult botle...
Even then insulate, insulate (and same again)
Then its a question of speed and how hot or cold) Battery pack that charges even when not used, used as buffer might work (for a short time).Controlling it from Arduino is easy part using function that switches one on other off whenever you want and then calling the function itself to make sure both steps happen, rather then manualy editing or using one output for controlling power on/off and another on two way relay switching between sets (relay would increase consumption here).

Noted- thanks for your insight on this.

In a word, no. Laptop or desktop computer usually have USB ports, which put out like 10 watts of power for a "high current" USB port. That is not enough to do much heating or cooling. You want a high power supply. The pelteir plates I've seen run on 12V DC. Get a 5A 12V supply, or even higher.
You might be able to draw larger amounts of current from a USB-C port or a USB-C power supply, but why? Get a dedicated high current power supply that puts out the maximum voltage your peltier plates can handle.
Note that there is no reason to have 2 plates for heating and 2 plates for cooling. Run the current one way and they heat. Reverse the current and they cool.
Also I'm not sure of the value of using 2 plates to cool. A single plate able to handle more power would likely be more efficient, and easier to insulate. (With 2 plates you'd need 2 heatsinks, which will allow twice as much heat to leak through when the power is off. Doubling the current you feed into a single plate should give double he heating/cooling, without increasing the heat leakage when it's off. Just make sure you don't exceed the maximum rated current of your plate, and that you have a large enough heatsink to handle the heat transfer.)
You could use an H-bridge meant for controlling motors to provide either +12V or -12V under software control. Those generally handle high current.
You could also use a digital thermometer and make a thermostatically controlled system. You'd measure the temp in the bottle, and when it got to your desired temp range, turn off the power. When the temp moved outside the desired range, you'd turn the power back on.

Thanks for the suggestions. I'm currently looking into some battery packs I can use for this. Again, Thanks!

You need a battery pack that provides the voltage your peltier plates need, and then look at the total capacity of the battery, in amp-hours. For example, if the peltier plate draws 2 amps, and the battery is rated for 2 amp-hours, the battery will run it for 1 hour.

Heating and cooling uses a great deal of power, and anything but a large heavy battery like a lead-acid car battery is going to be depleted quite quickly.


text:
Teensy4.1 with 2x 8MB PSRAM Chips: external_psram_size=0 but EXTMEM char[] works as expected?
So I got 2x PSRAM chips from PJRC with my Teensy4.1 and soldered them on (it's a hideous job as I lost my tips) but it's all tested with a multimeter and the connections are solid.
I ran the memtest sketch from here compiled in both Teensyduino and PlatformIO:
https://www.pjrc.com/store/psram.html
Aaaaand external_psram_size is reading 0 for both cases. Setting the memory size manually in the program also fails (even with 8MB).
However... EXTMEM vars work as expected. I'm not sure how the mem addressing actually works with the provided memtest program, either - it certainly doesn't seem to use EXTMEM anywhere.
Here's my memory tester (run to crash):
EXTMEM char bigBuf[10000000];
//char bigBuf[10000];
int c = 0;
void setup() {
  c = 0;
}

void loop() {
  bigBuf[c] = 'a';
  Serial.println(bigBuf[c]);
  Serial.println(String(c));
  c = c + 1000;
  delay(1);
}

Output with EXTMEM char[]: (as expected overflowed until 16MB)
a
0
a
100
...
a
16777100
a
16777200

Output with internal mem char[]: (as somewhat expected overflowed at 512K - max of RAM1)
a
0
a
100
...
a
488081
a
489081

Anyway, I'm glad EXTMEM works.. But can someone explain what's going on with the provided memtest? I admit I didn't read it over very well, but I thought that PSRAM could only be accessed via EXTMEM; how is it addressing otherwise?

I'm afraid your test program doesn't work as you intended. I tested it with a T4.1 without RAM soldered on and it gives the same result as in your question.

You didn't declare your array volatile. Thus, the compiler can (and probably will) simply optimize the reading back away.
Even if you declare the variable volatile the processor reads back the value from the cache line, i.e. you always get the correct value back, even without any external RAM.

Here a simple test program showing the effect. It always switches the LED on, even without external RAM soldered on the board.
EXTMEM volatile int test;

void setup()
{
    pinMode(13, OUTPUT);

    test = 42;
    if(test == 42)
    {
        digitalWriteFast(13, HIGH);
    }
}

void loop(){
}

Here the disassembly of the setup function. It clearly shows that the processor tries to store 42 in the (non existing) external RAM and reads it back from there. Obviously the read back value comes from the cache line.
(comments added by me)
void setup()
{
      7c:   push    {r3, lr}                         // pinMode code
    pinMode(13, OUTPUT);                             //
      7e:   movs    r1, #1                           //
      80:   movs    r0, #13                          //
      82:   bl  160c <pinMode>                       //-------------

    test = 42;
      86:   ldr r3, [pc, #20]   ; (9c <setup+0x20>)  // load r3 with address of 'test' (0x70000000, stored at 0x9C)
      88:   movs    r2, #42 ; 0x2a                   // load r2 with #42
      8a:   str r2, [r3, #0]                         // store content of r2 at address stored in r3. i.e., store #42 0x7000'0000 (EXTRAM)

    if(test == 42)
      8c:   ldr r3, [r3, #0]                         // volatile forces the compiler to read back 'test' (store it in r3)
      8e:   cmp r3, r2                               // check if equals r2 (contains #42)
      90:   bne.n   9a <setup+0x1e>                  // goto 0x9A if not equal

CORE_PIN13_PORTSET = CORE_PIN13_BITMASK;             // digitalwritefast code (next 3 lines)
      92:   ldr r3, [pc, #12]   ; (a0 <setup+0x24>)  // ...
      94:   movs    r2, #8                           // ...
      96:   str.w   r2, [r3, #132]  ; 0x84           // -------

      9a:   pop {r3, pc}                             // return from setup()

      9c:   .word   0x70000000                       // Address of 'test'; EXTRAM starts at 0x7000'000
      a0:   .word   0x42004000                       // Address of GPIO register for LED

Thanks for the input; it's odd EXTMEM only decides to crash at 16MB but that seems to be what's happening. You were right - I tried to actually read from a value assigned near the beginning of a 14MB EXTMEM array and got nothing. I read some stuff on the Teensy4.1 beta testing thread (Arduino forum I think) about a couple digital pins being used to detect the PSRAM chips... I'll have to look into that somehow, or hope someone has other ideas (I guess I may have fried one soldering - I'll desolder one and see if that helps). Thx again, never use C so didn't even consider volatile.

Paul here.  I'm the author of that memtest program, and also the creator of Teensy.  While luni64 already answered very well about your test program, hopefully I can add some clarity about the official memtest program.
Regarding "I thought that PSRAM could only be accessed via EXTMEM", indeed use of EXTMEM arrays or variables is the normal way.  But it is not the only way.  The memtest program uses pointers with the known address range of those memory chips.  Because the wires physically connect to the "FlexSPI2" peripheral inside the chip, the memory will always start at address 0x70000000.  You can find this detail on page 35 of the chip's reference manual.
https://www.pjrc.com/teensy/IMXRT1060RM_rev2.pdf
Unfortunately the manual is tough to read and confusing in so many ways.  Even on page 35, it describes the memory as "ciphertext", which might be the case if the Bus Encryption Engine (mentioned on page 184) were used in a certain way.  No encryption is used, and if you read page 184 you'll see that engine only does decryption, so it really only could be used for read-only memory which is pre-loaded with encrypted data.
The point is we know the RAM always starts at 0x70000000 because of the way the hardware is designed.  If you look at the memtest code, you'll see it creates 2 variables called "memory_begin" and "memory_end", which are pointers used to directly access the memory within that known address range.
The idea behind the memory test is the entire memory is filled with a known data pattern.  This sort of testing is meant to catch any (very unlikely) internal problems inside the memory chips, where writing to one place inside the chip might corrupt data somewhere else in the same chip.
The pointer used is declared with "volatile" which prevents the compiler from trying to optimize away actual memory access.
After the memory is completely filled, you'll see a function called arm_dcache_flush_delete() is used.  Even if you use volatile to keep the compiler from optimizing away memory access, the Cortex-M7 hardware has 32K level 1 cache.  This function causes the ARM Cortex-M7 processor to completely write any cached data to the actual memory chip, and then delete the data from its cache.  Normally these special cache functions are only used by low-level driver code using Direct Memory Access (DMA), where you need to be sure data you've written is actually in memory before instructing a peripheral to use DMA to directly grab it from the memory (generally DMA-based peripherals can't access the cache), or before you read data a peripheral put into memory using DMA.  Normally you don't need to mess with the cache, but this sort of hardware testing and special benchmarking are the other sort of application where special attention to the processor's cache is important.
Then the entire memory is read back, using the volatile pointer so the compiler doesn't try to do anything too smart.  As the data is read, every 32 bit word is compared to the original pattern written.  Again, the idea is to check for the pretty unlikely case where the memory appears to work, but could theoretically have an internal problem where writing to one place causes corruption somewhere else inside the chip.
The entire test is repeated many times.  A variety of fixed 32 bit patterns are used.  Many of the tests fill the entire memory with a pseudo-random sequence, of course doing the same verification where any change to even just 1 bit within the entire memory range will be detected and reported as a failure.  Maybe that's overkill, but I tried to design the memtest program according to best practices described for testing PC memory, and those are the ways experts recommend to test memory (actually they recommend even more sophisticated & complex patterns... maybe someday I'll add those).
Hopefully this helps answer "can someone explain what's going on with the provided memtest?"
Regarding the soldering, a problem other people have seen involves the solder adhering only to the memory chip pin.  Even though it looks ok when viewed from above, it's possible for the solder to be a blob resting just slightly above the pad surface on the circuit board.  I would recommend re-heating the solder.  Allow time for it to fully heat and flow onto the pad.  While extra time heating isn't wonderful for the PSRAM chip, those chips are pretty hearty heat-size and if the memory isn't working you really don't have much to lose.  Counting to 10 while reheating the solder usually works.  If you have any liquid flux chemical, applying that before reheating might also help.
Focus your repair effort first on the chip mounted to the smaller set of pads next to the edge of the PCB.  The startup code looks for the first 8MB chip in that location.  If won't even look for the other chip if no memory is detected in the first location.

It's amusing that ASE had me reviewing your "late answer". You know, to make sure that it was up to standards. Gee, I dunno... I guess it's alright. =)