# Question
Title: Best way to obtain angular velocity from a 9 DoF sensor
I have been using a BNO055 sensor (9° dof IMU) for a project which will use angular velocity to the mouse cursor on screen.

So far, I have gotten quaternion output from the sensor and been able to convert it to angular velocity in a couple of ways. The first, multiplying 1 quaternion sample by its conjugate in the next sample, and then converting the quaternion Delta in Euler angles. The second, converting from quaternions to Euler angles and then finding the change in those between samples.

Both methods result in angular velocity measurement, but each with their advantages and disadvantages. E.g. Quaternion Delta between samples does not suffer from gimbal lock, but it's difficult to isolate y-axis from z-axis movement.

I know that you can ask the sensor for angular velocity data directly, but apparently that's less precise due to the Gyro drift and it's relative orientation only, which is why I opted to work with quaternions.

Is there a better way to go about this?

My code included below for reference with the 2 approaches in case it's helpful/interesting. It uses the Adafruit repository, doing the standard stuff in setup function and then calling the function below in loop.

```
void quaternion_Delta () {
  // Quaternion data 1
  imu::Quaternion quat = bno.getQuat();
  // Euler 1
  imu::Vector<3> euler_one = quat.toEuler();
  //delay between samples
  delay(BNO055_SAMPLERATE_DELAY_MS);
  // Quaternion data 2
  imu::Quaternion quat_two = bno.getQuat();
  // Euler 2
  imu::Vector<3> euler_two = quat_two.toEuler();
  // quaternion comparison
  imu::Quaternion quatDelta = quat_two * quat.conjugate ();
  imu::Vector<3> euler = quatDelta.toEuler();
  Serial.print(" X: ");
  Serial.print(euler.x()*radius_to_degrees, 2);
  Serial.print(" Y: ");
  Serial.print(euler.y()*radius_to_degrees, 2);
  Serial.print(" Z: ");
  Serial.print(euler.z()*radius_to_degrees, 2);
  Serial.print("\t\t");
  // Euler comparison
  imu::Vector<3> euler_comparison = euler_two - euler_one;
  Serial.print(" x: ");
  Serial.print(euler_comparison.x()*radius_to_degrees, 2);
  Serial.print(" y: ");
  Serial.print(euler_comparison.y()*radius_to_degrees, 2);
  Serial.print(" z: ");
  Serial.print(euler_comparison.z()*radius_to_degrees, 2);
  Serial.print("\n");
  }

```

# Answer
> 1 votes
Consider building on Sebastian Madgwick's PhD IMU research. A GitHub Arduino project based on Madgwick's work can be found here.

---
Tags: sensors, imu, bno055
---


# Question
Title: What is the best way I can detect if a ping pong ball has hit the ping pong table?
The goal is to track points, which, in the case of ping pong, is how many times the ball has touched the table.

My concerns are with how light the ball and therefore the impact on the table will be. Is this too light for something like a vibration sensor to register?
Would you imagine the sensor working better on the paddles or the table?

I'm open to other suggestions on more reliable ways to track points other than vibration.

# Answer
> 3 votes
Having played ping-pong (badly) I think a microphone would be able to count ball/table impacts quite well. The 'click' sound is much higher than that of hitting the paddle, so you might be able to differentiate on that basis. You might consider a two microphone/transducer arrangement- one coupled to the table and one not touching the table. If you get a simultaneous signal on both, the ball has hit the table. If you get only one signal (from the not-touching microphone) then the ball has hit a paddle. This also gives you the option of getting some timing information.

---
Tags: sensors
---


title: Random servo movement with Arduino Uno

text:
# Question
Title: Random servo movement with Arduino Uno
Recently, I have been working on a project involving 8 Tower Pro SG90 servos and an Arduino Uno. The issue I am running into is that the servos will randomly move when connected, without even receiving a signal from the Arduino.

Specifically, sometimes the servos will work perfectly and the input moves the servos fine, but then all of a sudden the servos will start twitching and moving erratically back and forth. Then I disconnect the power and plug it back in and I will sometimes work again or sometimes not.

I don't think power is the problem because I am powering the servos externally with a 5.5 V power supply which can provide 2.5 A. I also made sure to have a common ground between the Arduino and the power supply. Additionally, I don't think this is an issue of a broken servo because I have this problem with all eight. In my code, I have input pins to control the servos which are just buttons. These buttons also have pull-down resistors, so I don't think the input is the problem either. I am using the Arduino servo library.

The only other thing I can think of is external frequency interference because some of the circuitry and wiring are close together, but none of the wires are very long and I even tried putting a ferrite bead on the servo cables but to no avail.

If anyone has any ideas about a solution to my problem which I have not tried yet that would be amazing!

```
#include <Servo.h>

Servo servo1;
Servo servo2;
Servo servo3;
Servo servo4;
Servo servo5;
Servo servo6;
Servo servo7;
Servo servo8;

void setup(){
  pinMode(5, INPUT);
  pinMode(4, INPUT);
  pinMode(3, INPUT);
  pinMode(2, INPUT);
  pinMode(1, INPUT);
  pinMode(A0, INPUT);
  pinMode(A1, INPUT);
  pinMode(A2, INPUT);
  servo1.attach(13);
  servo2.attach(12);
  servo3.attach(11);
  servo4.attach(10);
  servo5.attach(9);
  servo6.attach(8);
  servo7.attach(7);
  servo8.attach(6);
}

void loop(){
  if (digitalRead(5) == LOW) {
    servo1.write(120);
    delay(20);
  } else {
    servo1.write(50);
    delay(20);
  }

  if (digitalRead(4) == LOW) {
    servo2.write(110);
    delay(20);
  } else {
    servo2.write(200);
    delay(20);
  }

  if (digitalRead(3) == LOW) {
    servo3.write(120);
    delay(20);
  } else {
    servo3.write(50);
    delay(20);
  }

  if (digitalRead(2) == LOW) {
    servo4.write(110);
    delay(20);
  } else {
    servo4.write(200);
    delay(20);
  }

  if (digitalRead(1) == LOW) {
    servo5.write(120);
    delay(20);
  } else {
    servo5.write(50);
    delay(20);
  }

  if (digitalRead(A3) == LOW) {
    servo6.write(110);
    delay(20);
  } else {
    servo6.write(200);
    delay(20);
  }

  if (digitalRead(A2) == LOW) {
    servo7.write(120);
    delay(20);
  } else {
    servo7.write(50);
    delay(20);
  }

  if (digitalRead(A1) == LOW) {
    servo8.write(110);
    delay(20);
  } else {
    servo8.write(200);
    delay(20);
  }
}

```

# Answer
> 0 votes
You call servoX.write() repeatedly, even when no button has changed. Each call turns off interrupts briefly while the servo value is being updated. This happens, maybe 40 times/sec and may be messing up the servo timing in some non-constant way. Try only calling the servoX.write() functions once, only when its button-state has settled into a new state.

Update:

> could you provide an example please

```
  bool prevButton5 = LOW;            // one of these for each button
    :                                // outside of the loop() func.
    :

  if(digitalRead(5) != prevButton5){  // button changed?
    prevButton5 = !prevButton5;       // save new button state
    if(preButton5 == LOW){            // (your same code from here down)
      servo1.write(120);
      delay(20);
    }
    else{
      servo1.write(50);
      delay(20);
    }
  }

```
* Make a boolean for each button.
* Wrap each of your button segments as I did for button5. Notice that your code is now executed only if the associated button has changed, so you will have many fewer servoX.write() calls.

That isn't the totally best way to do it. I made it as straightforward as I could, even though the additional code gets replicated for every button. I'd probably write a single function that manages one button and one motor, and call that function for each button / motor pair.

I also ignored the concept of switch-bounce to keep the number of changes low, but you should look it up and consider it. Switch-bounce is *apparent* bouncing of the switch contacts for a few milli-seconds during the change from open to closed or vice-versa, which leads to several make-break-make.....-make cycles (or the reverse) when you push or release the button. I'd probably make (or search for) a button debounce function and call it for the particular button I'm testing if I see that button has changed.

First try the "rude and crude" fix I suggested and get that working. Then if you're interested, try making one or more of the refinements.

Update:

```
the servos still jitter and twitch esspecailly when
I move the whole arduino and wires around.

```

That suggests either or both of

* cross-talk;
* the plug wires' connections being less than solid, especially when the wires move.

Try:

* laying out the servo cables to keep them away from each other as much as possible;
* wiring only a few of the servos, and in different combinations;
* also try commenting out the code - or not - for those servos you disconnected in the previous step.

If it turns out to be the plug-in wires and if this project is intended to actually be used for something, I'd suggest using a screw-terminal shield on your Uno to attach the servo wires more securely.

---
Tags: servo
---


# Question
Title: Why is our refresh rate consistently decreasing in logging on SD card?
The current code is used to gather the state of 12 infrared beams and log them to an SD card using the real time clock to mark the time. The code uses a switch to turn the device on and off and an LED to indicate if data is being written to the SD. When we later looked at the data on the SD card the refresh rate was slowly decreasing and we ended up with only 10 logs a second after a few hours. Why is this happening and how is it fixed?

```
#include <SD.h>   //For talking to SD Card
#include <Wire.h>  //For RTC
#include "RTClib.h" //For RTC

//Define pins
//SD card is on standard SPI pins
//RTC is on Standard I2C Pins
const int CS_PIN   = 53;

//Default rate of 25ms
int refresh_rate = 25;

//Define RTC object
RTC_DS1307 RTC;

//Initialize variables
String year, month, day, hour, minute, second, time, date;

#define SENSOR1 22
#define SENSOR2 23
#define SENSOR3 24
#define SENSOR4 25
#define SENSOR5 26
#define SENSOR6 27
#define SENSOR7 32
#define SENSOR8 33
#define SENSOR9 34
#define SENSOR10 35
#define SENSOR11 36
#define SENSOR12 37
#define LEDPIN 6
#define SWITCH 10

// variables will change:
int sensorState1 = 0, lastState1 = 0;
int sensorState2 = 0, lastState2 = 0;
int sensorState3 = 0, lastState3 = 0;
int sensorState4 = 0, lastState4 = 0;
int sensorState5 = 0, lastState5 = 0;
int sensorState6 = 0, lastState6 = 0;
int sensorState7 = 0, lastState7 = 0;
int sensorState8 = 0, lastState8 = 0;
int sensorState9 = 0, lastState9 = 0;
int sensorState10 = 0, lastState10 = 0;
int sensorState11 = 0, lastState11 = 0;
int sensorState12 = 0, lastState12 = 0;

//Variable for reading the Switch Status
int SWITCHSTATE ;

//define integers for sensor change
int SensorChange1 = 0;
int SensorChange2 = 0;
int SensorChange3 = 0;
int SensorChange4 = 0;
int SensorChange5 = 0;
int SensorChange6 = 0;
int SensorChange7 = 0;
int SensorChange8 = 0;
int SensorChange9 = 0;
int SensorChange10 = 0;
int SensorChange11 = 0;
int SensorChange12 = 0;

void setup()
{
  // initialize the sensor pin 24 as an input:
  pinMode(SENSOR1, INPUT);
  digitalWrite(SENSOR1, HIGH); // turn on the pullup  // initialize the sensor pin 25 as an input:
  pinMode(SENSOR2, INPUT);
  digitalWrite(SENSOR2, HIGH); // initialize the sensor pin 26 as an input:
  pinMode(SENSOR3, INPUT);
  digitalWrite(SENSOR3, HIGH); // initialize the sensor pin 27 as an input:
  pinMode(SENSOR4, INPUT);
  digitalWrite(SENSOR4, HIGH); // initialize the sensor pin 28 as an input:
  pinMode(SENSOR5, INPUT);
  digitalWrite(SENSOR5, HIGH); // initialize the sensor pin 29 as an input:
  pinMode(SENSOR6, INPUT);
  digitalWrite(SENSOR6, HIGH);  // initialize the sensor pin 30 as an input:
  pinMode(SENSOR7, INPUT);
  digitalWrite(SENSOR7, HIGH);  // initialize the sensor pin 31 as an input:
  pinMode(SENSOR8, INPUT);
  digitalWrite(SENSOR8, HIGH);  // initialize the sensor pin 32 as an input:
  pinMode(SENSOR9, INPUT);
  digitalWrite(SENSOR9, HIGH);  // initialize the sensor pin 33 as an input:
  pinMode(SENSOR10, INPUT);
  digitalWrite(SENSOR10, HIGH);  // initialize the sensor pin 34 as an input:
  pinMode(SENSOR11, INPUT);
  digitalWrite(SENSOR11, HIGH);  // initialize the sensor pin 35 as an input:
  pinMode(SENSOR12, INPUT);
  digitalWrite(SENSOR12, HIGH);   // initialize the LED pin as an output:

// initialize the LED pin as an output:
  pinMode (LEDPIN, OUTPUT);

// initialize the SWITCH pin as an output:
  pinMode (SWITCH, INPUT);

// setpin 19 as high (5V) and 18 as low
  pinMode(19, OUTPUT);
  pinMode(18, OUTPUT);
  digitalWrite(19, HIGH);
  digitalWrite(18, LOW);

  Serial.begin(9600);
  Serial.println(F("Initializing Card"));

 //CS pin, and pwr/gnd pins are outputs
  pinMode(CS_PIN, OUTPUT);

  //Initiate the I2C bus and the RTC library
  Wire.begin();
  RTC.begin();

  //If RTC is not running, set it to the computer's compile time
  if (! RTC.isrunning())
  {
    Serial.println(F("RTC is NOT running!"));
    RTC.adjust(DateTime(__DATE__, __TIME__));
  }

  //Initialize SD card
  if (!SD.begin(CS_PIN))
  {
    Serial.println(F("Card Failure"));
    return;
  }
  Serial.println(F("Card Ready"));

  //Read the configuration information (speed.txt)
  File commandFile = SD.open("speed.txt");
  if (commandFile)
  {
    Serial.println(F("Reading Command File"));

    while(commandFile.available())
    {
      refresh_rate = commandFile.parseInt();
    }
    Serial.print(F("Refresh Rate = "));
    Serial.print(refresh_rate);
    Serial.println(F("ms"));
    commandFile.close();
  }
  else
  {
    Serial.println(F("Could not read command file."));
    return;
  }

}

void loop()
{
  SWITCHSTATE = digitalRead(SWITCH); //read input value
  if (SWITCHSTATE == LOW)
 {
   digitalWrite(LEDPIN, LOW);
 }
  else
 {
   digitalWrite(LEDPIN, HIGH);

// read the state of the sensor value:
  sensorState1 = digitalRead(SENSOR1);
  sensorState2 = digitalRead(SENSOR2);
  sensorState3 = digitalRead(SENSOR3);
  sensorState4 = digitalRead(SENSOR4);
  sensorState5 = digitalRead(SENSOR5);
  sensorState6 = digitalRead(SENSOR6);
  sensorState7 = digitalRead(SENSOR7);
  sensorState8 = digitalRead(SENSOR8);
  sensorState9 = digitalRead(SENSOR9);
  sensorState10 = digitalRead(SENSOR10);
  sensorState11 = digitalRead(SENSOR11);
  sensorState12 = digitalRead(SENSOR12);

  //Get the current date and time info and store in strings
  DateTime datetime = RTC.now();
  year  = String(datetime.year(),  DEC);
  month = String(datetime.month(), DEC);
  day  = String(datetime.day(), DEC);
  hour  = String(datetime.hour(), DEC);
  minute = String(datetime.minute(), DEC);
  second = String(datetime.second(), DEC);

  //Concatenate the strings into date and time
  date = year + "/" + month + "/" + day;
  time = hour + ":" + minute + ":" + second;

  if (sensorState1 == HIGH)
  {
   SensorChange1 = 1;
  }
  else
  {
   SensorChange1 = 0;
  }
  if (sensorState2 == HIGH)
  {
   SensorChange2 = 1;
  }
  else
  {
   SensorChange2 = 0;
  }
  if (sensorState3 == HIGH)
  {
   SensorChange3 = 1;
  }
  else
  {
   SensorChange3 = 0;
  }
  if (sensorState4 == HIGH)
  {
   SensorChange4 = 1;
  }
  else
  {
   SensorChange4 = 0;
  }
  if (sensorState5 == HIGH)
  {
   SensorChange5 = 1;
  }
  else
  {
   SensorChange5 = 0;
  }
  if (sensorState6 == HIGH)
  {
   SensorChange6 = 1;
  }
  else
  {
   SensorChange6 = 0;
  }
  if (sensorState7 == HIGH)
  {
   SensorChange7 = 1;
  }
  else
  {
   SensorChange7 = 0;
  }
  if (sensorState8 == HIGH)
  {
   SensorChange8 = 1;
  }
  else
  {
   SensorChange8 = 0;
  }
  if (sensorState9 == HIGH)
  {
   SensorChange9 = 1;
  }
  else
  {
   SensorChange9 = 0;
  }
  if (sensorState10 == HIGH)
  {
   SensorChange10 = 1;
  }
  else
  {
   SensorChange10 = 0;
  }
  if (sensorState11 == HIGH)
  {
   SensorChange11 = 1;
  }
  else
  {
   SensorChange11 = 0;
  }
  if (sensorState12 == HIGH)
  {
   SensorChange12 = 1;
  }
  else
  {
   SensorChange12 = 0;
  }

  File dataFile ;
  dataFile = SD.open("log1.csv", FILE_WRITE);
  if (dataFile)
    {
      dataFile.print(date);
      dataFile.print(F(","));
      dataFile.print(time);
      dataFile.print(F(","));
      dataFile.print(SensorChange1);
      dataFile.print(F(","));
      dataFile.print(SensorChange2);
      dataFile.print(F(","));
      dataFile.print(SensorChange3);
      dataFile.print(F(","));
      dataFile.print(SensorChange4);
      dataFile.print(F(","));
      dataFile.print(SensorChange5);
      dataFile.print(F(","));
      dataFile.print(SensorChange6);
      dataFile.print(F(","));
      dataFile.print(SensorChange7);
      dataFile.print(F(","));
      dataFile.print(SensorChange8);
      dataFile.print(F(","));
      dataFile.print(SensorChange9);
      dataFile.print(F(","));
      dataFile.print(SensorChange10);
      dataFile.print(F(","));
      dataFile.print(SensorChange11);
      dataFile.print(F(","));
      dataFile.print(SensorChange12);
      dataFile.println( );
      dataFile.close(); //Data isn't actually written until we close the connection!

      //Print same thing to the screen for debugging
      Serial.println();
      Serial.print(date);
      Serial.print(F(","));
      Serial.print(time);
      Serial.print(F(","));
      Serial.print(SensorChange1);
      Serial.print(F(","));
      Serial.print(SensorChange2);
      Serial.print(F(","));
      Serial.print(SensorChange3);
      Serial.print(F(","));
      Serial.print(SensorChange4);
      Serial.print(F(","));
      Serial.print(SensorChange5);
      Serial.print(F(","));
      Serial.print(SensorChange6);
      Serial.print(F(","));
      Serial.print(SensorChange7);
      Serial.print(F(","));
      Serial.print(SensorChange8);
      Serial.print(F(","));
      Serial.print(SensorChange9);
      Serial.print(F(","));
      Serial.print(SensorChange10);
      Serial.print(F(","));
      Serial.print(SensorChange11);
      Serial.print(F(","));
      Serial.print(SensorChange12);

    }
    else
    {
     Serial.println(F("Couldn't open log file"));
    }

  lastState1 = sensorState1;
  lastState2 = sensorState2;
  lastState3 = sensorState3;
  lastState4 = sensorState4;
  lastState5 = sensorState5;
  lastState6 = sensorState6;
  lastState7 = sensorState7;
  lastState8 = sensorState8;
  lastState9 = sensorState9;
  lastState10 = sensorState10;
  lastState11 = sensorState11;
  lastState12 = sensorState12;

  delay(refresh_rate);
  }

  }

```

# Answer
I don't have certain answer for you, but a deep suspicion. ~~If I get bored I'll confirm it.~~ Confirmed below.

In each pass of `loop()`, you have:

```
  dataFile = SD.open("log1.csv", FILE_WRITE);

```

In short, finding the end of the file is linear operation in a FAT filesystem. It must follow the allocation chain to find (or create), the last cluster of the file. The allocation chain is sort like a linked list with the links themselves being the only thing in linked list structure; their numbers are mapped onto the cluster numbers. So you're traversing a linked list, except you may be doing it across multiple sectors of an SD card, which is comparatively expensive.

So by reopening repeatedly in `loop()`, you're forcing it to perform this lengthening process each time, apparently because of:

```
dataFile.close(); //Data isn't actually written until we close the connection!

```

The part of `.close();` that does this is made available to you as `.flush();`, without needing to close the file and forget where the current cluster is.

In other words, you should be able to `open()` the file once in `setup()` and replace your `.close()` in `loop()` with a `.flush()`.

That said, you needn't and probably shouldn't flush on every record write. If you're doing this so that you can shut the device down, you might want to just add a push-button that does the closing or flushing and then waits in the tight loop until it's power cycled.

# Confirmation Test Results

In short, yes, there's a measurable, file-size related cost to opening the file for write and seeking to the end. And it's just a fact about the FAT filesystem and noticeable because it's impractical to load the whole allocation table into memory on a small Arduino. It would normally (e.g on the desktop) be loaded into memory and you'd scarcely notice the difference in opening files of different sizes.

In my one tested scenario for my setup the numbers predict that when the file grows to approximately 155 Meg, it will take about a tenth of a second to open.

This test involved:

* An Arduino UNO.
* 2 GB FAT16 formatted card.
* Arduino AVR core version 1.8.3
* SD card library version 1.2.4.

Your results will probably vary widely with MCU type and filesystem block size, but so long as you're using a Arduino with a SD library that minimizes memory footprint, you'll have a noticeable increasing open time with larger file sizes.

The below is going to be a bit nerdy, but since people seem to be interested in it, I'm giving some detail. Arduino code follows at the bottom for what was used to collect the data that produced the graph.

I emptied a 2 GByte SD card. This included removing the "System Volume Information" that windows (or perhaps the card maker) had put on there, and confirmed that were were no allocated clusters, no file chains. Under these conditions the file should just grow in consecutive sectors on the card; at least as presented by the card, as in: if we ignore anything the card might be doing for wear-leveling. The pattern used in the program makes it pretty easy to just look at a raw image of the card and see that this is what happened.

Anyway, with my setup these are some results:

The 98304 sector count on the right refers to a file of roughly 50 Meg.

This SD card is FAT16 formatted, something I hadn't noticed until I ran the numbers on that staircase pattern and found them defying expectations by a factor of 2.

Being FAT16, each FAT table sector, has 512/2 = 256 entries in it. Each entry number corresponds to one cluster (block), which for my SD card's filesystem happens to be 32 kByte, or 64 count of 512-byte sectors. So every FAT table sector (in my case) is responsible for locating 64 * 256 = 16,384 file sectors. In other words, the staircase pattern appears to reflect the fact that following the allocation chain for our consecutive file means reading another FAT table sector for every 16,384 sectors of the file, hence the jumps at those intervals.

* If you used a fragmented file it would need to do this more often and the performance would look worse. *I did inspect the SD card to confirm that it was written sequentially.*
* If you use FAT32, you can expect it to take longer because each FAT sector will store half as many cluster references.
* If you use smaller cluster (block) size, then it will take longer because each enter in the FAT sector covers less file content.

## Test code

```
//
// Tested on an UNO with Arduino Core version 1.8.3
// 2 GByte SDCard
//

#include <SD.h> // Version 1.2.4 as of test.
#include <SPI.h>

static constexpr int PIN_SDCARD_SHIELD_CHIP_SELECT = 10;
static constexpr int PIN_HALT_TEST                 =  2;

static const char test_filename[] = "testfile.txt";

struct test_state : Printable {
  uint32_t      sector_counter = -1;
  unsigned long open_duration  =  0;

  size_t printTo(Print& p) const override {
    auto r = p.write('[');
    r     += p.print(sector_counter);
    r     += p.write(':');
    r     += p.print(open_duration);
    r     += p.write(']');
    return r;
  }

  void update(unsigned long new_open_duration) {
    open_duration = new_open_duration;
    ++sector_counter;
  }
};

//
//
//
void write_numbered_sector(
  Print &p,
  const test_state &state
) {
  static constexpr size_t SECTOR_SIZE            = 512;
  static constexpr size_t CR_LF_SIZE             =   2;

  const auto printed_test_state_len = p.print(state);

  const auto xs_to_write =
      SECTOR_SIZE
    - printed_test_state_len
    - CR_LF_SIZE;

  for (size_t i = xs_to_write; i != 0; --i) {
    p.write('X');
  }

  p.write('\r');
  p.write('\n');
}

//
//
//
void setup() {
  pinMode(PIN_HALT_TEST, INPUT_PULLUP);

  Serial.begin(9600);

  if (!SD.begin(PIN_SDCARD_SHIELD_CHIP_SELECT)) {
    Serial.println(F("Card initialization failed."));
    halt_test();
  }

  SD.remove(test_filename);
}

//
//
//
void blink_forever() {
  pinMode(LED_BUILTIN, OUTPUT);
  while (true) {
    static bool led_state = false;

    led_state = !led_state;
    digitalWrite(LED_BUILTIN, led_state);
    delay(100);
  }
}

//
//
//
void halt_test() {
  SD.end();
  SPI.end();
  Serial.end();

  blink_forever();
}

//
//
//
void loop() {
  static test_state state;

  Serial.flush();
  const auto started_opening = micros();
  File testfile = SD.open(test_filename, FILE_WRITE);
  const auto done_opening = micros();

  const auto open_duration = done_opening - started_opening;

  state.update(open_duration);

  write_numbered_sector(
    testfile,
    state
  );
  testfile.close();
  Serial.print(micros());
  Serial.print(' ');
  Serial.println(state);

  const auto user_requested_halt = (digitalRead(PIN_HALT_TEST) == LOW);
  if (user_requested_halt) {
    Serial.println(F("Test halt requested."));
    halt_test();
  }
}

//  vim:sw=2:ts=2:et:nowrap:ft=cpp:

```
> 25 votes

---
Tags: frequency, sd
---


title: Pushbutton to initiate a 5 time flash

text:
# Question
Title: Pushbutton to initiate a 5 time flash
The following code operates in a way that LED starts to flash only if the pushbutton is pushed for one second. I want to change this and make the LED flash for 5 times, immediately on push, regardless if the button is held "long" or released immediately. Can anyone help me out with this? I'm using the LC\_baseTools library btw. I managed to do this with another library with `doFlash(5)` but I have to work with LC basetools in this scenario and I can't figure out how to do it.

```
#include <mechButton.h>
#include <blinker.h>

#define BUTTON_PIN   11
#define LED_PIN      13
#define BLINK_MS     500.0
#define HOLD_MS      1000

mechButton  theButton(BUTTON_PIN);                    // A debounced button object. (Hook button between pin & ground)
blinker     theBlinker(LED_PIN,BLINK_MS/2,BLINK_MS);  // A fire and forget blinker object.
timeObj     pushTimer(HOLD_MS);                       // A timer object

void setup(void) {
   theBlinker.setOnOff(false);            // Make sure the blinker is acutally off.
   theButton.setCallback(btnClicked);     // Set the callback for the button.
}

// This gets called when the button is clicked.
void btnClicked(void) {
   if (!theButton.trueFalse()) {    // If it has been grounded..
      pushTimer.start();            // Start the timer.
      theBlinker.setPercent(100);   // Set the blinker to full on.
      theBlinker.setOnOff(true);    // Fire it up.
   } else {                         // Else, button released..
      theBlinker.setOnOff(false);   // SHut off the blinker.
   }
}

void loop(void) {
   idle();                             // idle runs the stuff in the background (button & binker)
   if (!theButton.trueFalse()) {       // If the button is currently pressed..
      if (pushTimer.ding()) {          // If the timer has expired..
         theBlinker.setPercent(50);    // Start blinking!
      }
   }
}

```

# Answer
First of all, considering your comment: "*I don't have time \[...\] to tackle arduino programming*" - If you don't learn how to code, then you can't work with code (and that includes putting together libraries you find on the internet). And learning takes time, it's that simple.

I recommend you forget about those libraries and implement that easy task from scratch, so you actually learn something. The below code has the logic you ask for, try to understand what it does.

```
#define BUTTON_PIN   11
#define LED_PIN      13

bool button_was_pressed=false;

void setup(){
  pinMode(LED_PIN,OUTPUT);
}

void loop() {
  if (digitalRead(BUTTON_PIN)) {
    if(!button_was_pressed) {
      for (int i=0;i<5;i++) {
        digitalWrite(LED_PIN,HIGH);
        delay(50);
        digitalWrite(LED_PIN,LOW);
        delay(50);
      }
    }
    button_was_pressed=true;
  }
  else {
    button_was_pressed=false;
  }
}

```

...pretty simple and it's only a few lines. You may want to debounce the button and use a non-blocking coding style, but that's a different chapter.

My advice is that you learn programming in a structured manner, e.g. by watching tutorials. A Q&A site is not the right place to do so, as we only answer questions.
> 1 votes

# Answer
> I managed to do this with another library with "doFlash(5)" but I have to work with LC basetools in this scenario and I can't figure out how to do it.

It looks like you are still allowed to write Arduino code in your sketch, so why not use the `BlinkWithoutDelay` "concept" and just write your own code.

I would favour an OOP solution for the LED flashing part of your requirement.

```
// Arduino IDE 1.8.9.
// Sketch uses 1126 bytes (3%) of program storage space.
// Global variables use 25 bytes (1%) of dynamic memory.
class Flasher{

  private:

    byte ledPin;
    byte ledState;
    unsigned int flashCounter;
    unsigned long highTime;
    unsigned long lowTime;
    unsigned long previousMillis;

  public:

    Flasher(byte ledPinNumber, unsigned long ledOnTime, unsigned long ledOffTime){
      ledPin = ledPinNumber;
      ledState = LOW;
      highTime = ledOnTime;
      lowTime = ledOffTime;
      previousMillis = 0;
      pinMode(ledPinNumber, OUTPUT);
      digitalWrite(ledPinNumber, LOW);
    }

    void Update(){

      // Check to see if it's time to change the state of the LED.
      unsigned long currentMillis = millis();

      if((ledState == HIGH) && (currentMillis - previousMillis >= highTime) && ((flashCounter > 0))){
        ledState = LOW;
        previousMillis += highTime;
        digitalWrite(ledPin, ledState);
        if(flashCounter > 0){flashCounter--;}
      }
      else if((ledState == LOW) && (currentMillis - previousMillis >= lowTime) && ((flashCounter > 0))){
        ledState = HIGH;
        previousMillis += lowTime;
        digitalWrite(ledPin, ledState);
        if(flashCounter > 0){flashCounter--;}
      }
    }

    void Start(unsigned int flashNumberOfTimes){
      flashCounter = flashNumberOfTimes * 2;
      ledState = LOW;
      digitalWrite(ledPin, ledState);
    }

    void Stop(){
      Start(0);
    }

    void SetPinHighTime(unsigned long pinHighTime){
      highTime = pinHighTime;
    }

    void SetPinLowTime(unsigned long pinLowTime){
      lowTime = pinLowTime;
    }

};

// Flasher object_name(Pin Number, ON Time MS, OFF Time MS);
Flasher led1(LED_BUILTIN, 500, 500);

void setup(){

  // Flash the LED 5 times.
  led1.Start(5);

}

void loop(){

  // Call the Update function as fast as possible.
  led1.Update();

}

```
> 1 votes

---
Tags: led, button
---


# Question
Title: Where is the documentation for writing an Arduino core?
I'm interested in writing an "Arduino core" (i. e. porting Arduino to a new MCU and new board(s)). I'm having trouble finding much documentation on how to do so. Am I missing something?

This page says "anyone may develop a core for their own boards following the rules and requirements we have issued." So, where are those "rules and requirements?"

I found something called the "Platform Specification", which sounded promising, but it only documents the config files; it does not say anything about the code that needs to be written to support a new platform.

I found ArduinoCore-API, which says it is the "hardware independent layer of Arduino core." But it doesn't mention anything about how to write the hardware-dependent part of the core.

I'd be grateful if anyone could point me to the Arduino core documentation. It's not turning up in my web searches. Thanks!

**Clarifications:**

* Yes, I can look at existing cores as examples, but I'd rather have the documentation, as well. Especially since existing cores may be of varying quality, or may not be up to the latest standard. Documentation is always a good thing.
* The reason I want to write a core is because... I want to use an MCU which is not currently supported! (Specifically, I want to add support for the GD32F350, but really that shouldn't be relevant to answering "Where is the documentation?")

# Answer
> 3 votes
There are two major parts to writing an Arduino core: the hardware independent portions and the hardware dependent.

The hardware independent portions are pretty much done for you in the ArduinoCore-API. However I wouldn't just use that verbatim but use it as a starting point and adapt it to your needs. This is because it actually has a couple of unresolved issues and not everything may 100% fit your needs. We don't use it for the chipKIT core because:

* It has an unresolved issue around the naming of the `String.h` file which conflicts with the libc's `string.h` on case insensitive filesystems
* Our USB stack is vastly different to how the Arduino "Pluggable USB" works
* We have extra facilities in a number of standard objects to make use of more efficient use of more advanced hardware

Once you have the hardware independent portion sorted you need to write, from scratch, the hardware dependent portion. The basic list of functions you *need* to implement are listed in the Arduino reference. How you write them cannot be documented, since that depends on the hardware. And you may well need to (or want to) write considerably more functions that just those. For example on chipKIT as well as the standard `analogWrite()` function we also have functions to change the PWM frequency and resolution - things that aren't part of the "standard", but are incredibly useful.

A good starting point is to examine the Arduino.h file of an existing core (the AVR core is a good baseline) which will list most of the functions and their parameter/return types. That gives you what the functions expect to receive and what they should emit, but *how* those functions are written is completely down to you.

And then of course you have to implement the boards variants etc to make the whole things work...

Also, be warned that writing (and maintaining) a core is a long and involved process and will consume the rest of your life.

---
Tags: documentation, board
---


# Question
Title: Can't read data from registers using I2C
I am trying to read data from the registers 6, 7, 8 and 9 of the STC3100 (Data Sheet) using an arduino uno.

I followed this tutorial: https://howtomechatronics.com/tutorials/arduino/how-i2c-communication-works-and-how-to-use-it-with-arduino/ And adjusted the device and register adress accordingly.

This isn't working and instead of returning the data on the register I'm just getting 16 over and over again.

Here is my code:

```
#include <Wire.h>
int ADXLAddress = 0x70;

#define X_Axis_Register_DATAX0 0x08

#define X_Axis_Register_DATAX1 0x09

#define Power_Register 0x00

int X0,X1,X_out;

void setup() {

  Wire.begin();

  Serial.begin(9600);
  delay(100);
  Wire.beginTransmission(ADXLAddress);
  Wire.write(Power_Register);
  Wire.write(16);
  Wire.endTransmission();
}
void loop() {
  delay(2000);
  Wire.beginTransmission(ADXLAddress);

  Wire.write(X_Axis_Register_DATAX0);
  Wire.write(X_Axis_Register_DATAX1);

  Wire.endTransmission();

  Wire.requestFrom(ADXLAddress,2);

  if(Wire.available()<=2) {
    X0 = Wire.read();
    X1 = Wire.read();
  }

  Serial.print("X0= ");
  Serial.print(X0, BIN);
  Serial.print("   X1= ");
  Serial.println(X1, BIN);
}

```

# Answer
> 1 votes
The following code shows, how I would read from a STC3100. But I own none of them, so I can not try the code. I would be very surprised if it works directly. Use it as an example. Perhaps we could improve it together. ;-)

```
#include <Wire.h>

#define STC_ADDRESS 0x70
#define MODE_REGISTER 0x00
#define CURRENT_LOW_REGISTER 0x06
#define VOLTAGE_LOW_REGISTER 0x08

int voltage, current;
int high_value = 0;

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

  Wire.begin();
  delay(100);
  // power on the STC
  Wire.beginTransmission(STC_ADDRESS);
  Wire.write(MODE_REGISTER);
  Wire.write(16);
  Wire.endTransmission();
}

void loop()
{
  Wire.beginTransmission(STC_ADDRESS);
  Wire.write(VOLTAGE_LOW_REGISTER);
  Wire.requestFrom(STC_ADDRESS, 2);
  delay(500);
  if( Wire.available() > 0 )
  {
    voltage = Wire.read();
    //Serial.print("REG 8 = ");
    //Serial.println(voltage);
  }
  delay(500);
  if( Wire.available() > 0 )
  {
    high_value = Wire.read();
    //Serial.print("REG 9 = ");
    //Serial.println(high_value);
    voltage += (high_value << 8);
    //Serial.print("voltage = ");
    //Serial.println(voltage);

  }
  Wire.endTransmission();

  Wire.beginTransmission(STC_ADDRESS);
  Wire.write(CURRENT_LOW_REGISTER);
  Wire.requestFrom(STC_ADDRESS, 2);
  delay(500);
  if( Wire.available() > 0 )
  {
    current = Wire.read();
    //Serial.print("REG 6 = ");
    //Serial.println(current);
  }
  delay(500);
  if( Wire.available() > 0 )
  {
    high_value = Wire.read();
    //Serial.print("REG 7 = ");
    //Serial.println(high_value);
    current += (high_value << 8);
    //Serial.print("current = ");
    //Serial.println(current);
  }
  Wire.endTransmission();

  Serial.print("V= ");
  Serial.print(voltage);
  Serial.print("   C= ");
  Serial.println(current);
}

```

---
Tags: arduino-uno, i2c
---


title: Adding another flow sensor to sketch

text:
# Question
Title: Adding another flow sensor to sketch
Adding another flow sensor to sketch

I have a water flow sketch I use for my freshwater consumption. I would like to adapt it to use for diesel fuel consumption. The difference is with a diesel motor the fuel pump sucks more fuel than it burns from the fuel tank and simply returns the excess to the fuel tank. ie there are 2 hoses from the fuel tank, one to the motor, and one back to the tank. The difference between what went to the motor and what went back to the tank is how much fuel the motor burned.

So my plan is to have 2 flow sensors (Yf-s201), and subtract the out put of one from the other and print the difference.

I have a sketch that already works to print L/m and total L. For one sensor on PIN D2. I have defined another sensor on PIN D3.

```
byte sensorInterrupt = 0;  // 0 = digital pin 2
byte sensorPin       = 2;

byte sensorInterrupt2 = 1;  //11 = digital pin 3
byte sensorPin2       = 3;

```

My first road block is to print them individually. as is they both just add to a single total.

I have tried to just copy bits of code and add a "2" but I really don't have any programing knowledge so I am just stabbing in the dark. I don't understand how to call upon the value the code has calculated.

This is the whole sketch:

```
/*
Liquid flow rate sensor -DIYhacking.com Arvind Sanjeev

Measure the liquid/water flow rate using this code.
Connect Vcc and Gnd of sensor to arduino, and the
signal line to arduino digital pin 2.

 */
// include the library code:
#include <Wire.h>
#include <LiquidCrystal_I2C.h>

LiquidCrystal_I2C lcd(0x27,20,4);

byte statusLed    = 13;

byte sensorInterrupt = 0;  // 0 = digital pin 2
byte sensorPin       = 2;

byte sensorInterrupt2 = 1;  // 1 = digital pin 3
byte sensorPin2       = 3;

// The hall-effect flow sensor outputs approximately 4.5 pulses per second per
// litre/minute of flow.
float calibrationFactor = 7.55;  //biger more / min

volatile byte pulseCount;

float flowRate;
unsigned int flowMilliLitres;
unsigned long totalMilliLitres;

unsigned long oldTime;

void setup()
{

  // Initialize a serial connection for reporting values to the host
  Serial.begin(9600);
lcd.init();
lcd.backlight();
     lcd.begin(16, 2);
   lcd.clear();
   lcd.setCursor(0,0);
   lcd.print("S.V. SAVANNAH");
   lcd.setCursor(0,1);
   lcd.print("DAY TANK FLOW METER");

  // Set up the status LED line as an output
  pinMode(statusLed, OUTPUT);
  digitalWrite(statusLed, HIGH);  // We have an active-low LED attached

  pinMode(sensorPin, INPUT);
  digitalWrite(sensorPin, HIGH);

  pulseCount        = 0;
  flowRate          = 0.0;
  flowMilliLitres   = 0;
  totalMilliLitres  = 0;
  oldTime           = 0;

  // The Hall-effect sensor is connected to pin 2 which uses interrupt 0.
  // Configured to trigger on a FALLING state change (transition from HIGH
  // state to LOW state)
  attachInterrupt(sensorInterrupt, pulseCounter, FALLING);
}

/**
 * Main program loop
 */
void loop()
{

   if((millis() - oldTime) > 1000)    // Only process counters once per second
  {
    // Disable the interrupt while calculating flow rate and sending the value to
    // the host
    detachInterrupt(sensorInterrupt);

    // Because this loop may not complete in exactly 1 second intervals we calculate
    // the number of milliseconds that have passed since the last execution and use
    // that to scale the output. We also apply the calibrationFactor to scale the output
    // based on the number of pulses per second per units of measure (litres/minute in
    // this case) coming from the sensor.
    flowRate = ((1000.0 / (millis() - oldTime)) * pulseCount) / calibrationFactor;

    // Note the time this processing pass was executed. Note that because we've
    // disabled interrupts the millis() function won't actually be incrementing right
    // at this point, but it will still return the value it was set to just before
    // interrupts went away.
    oldTime = millis();

    // Divide the flow rate in litres/minute by 60 to determine how many litres have
    // passed through the sensor in this 1 second interval, then multiply by 1000 to
    // convert to millilitres.
    flowMilliLitres = (flowRate / 60) * 1000;

    // Add the millilitres passed in this second to the cumulative total
    totalMilliLitres += flowMilliLitres;

    unsigned int frac;

    // Print the flow rate for this second in litres / minute
    Serial.print("Flow rate: ");
    Serial.print(int(flowRate));  // Print the integer part of the variable
    Serial.print("L/min");
    Serial.print("\t");       // Print tab space

    // Print the cumulative total of litres flowed since starting
    Serial.print("Output Liquid Quantity: ");
    Serial.print(totalMilliLitres);
    Serial.println("mL");
    Serial.print("\t");       // Print tab space
  Serial.print(totalMilliLitres/1000);
  Serial.print("L");

      lcd.clear();
      lcd.setCursor(4,0);
      lcd.print(int(flowRate));  // Print the integer part of the variable
      lcd.print("L/min ");

    // Print the cumulative total of litres flowed since starting
    lcd.setCursor(2,1);
    lcd.print("Total ");
  lcd.print(totalMilliLitres/1000.00);
  lcd.print("L");

    // Reset the pulse counter so we can start incrementing again
    pulseCount = 0;

    // Enable the interrupt again now that we've finished sending output
    attachInterrupt(sensorInterrupt, pulseCounter, FALLING);
  }
}

/*
Insterrupt Service Routine
 */
void pulseCounter()
{
  // Increment the pulse counter
  pulseCount++;
}'''

```

# Answer
> 1 votes
Your code currently does not use the second flow sensor. I guess you have problems in designing the code, so I try to walk you trough.

First let's look at the prerequisites, that are needed for the two flow sensors. You already have defined the pins of the flow sensors. You are also defining the number of the corresponding interrupts. In fact you don't have to do that. You can easily get the number of the interrupt through the function `digitalPinToInterrupt(pin)`. So we are left with the pin definition. I would suggest using clearer names:

```
int flow_out_pin = 2;
int flow_in_pin = 3;

```

`flow_out` meaning leaving the tank, `flow_in` coming back into the tank.

Then in `setup()` we need to initiate the pins. You have this

```
pinMode(sensorPin, INPUT);
digitalWrite(sensorPin, HIGH);

```

This can be then made shorter in one line per sensor:

```
pinMode(flow_out_pin, INPUT_PULLUP);
pinMode(flow_in_pin, INPUT_PULLUP);

```

Now we attach the interrupts to the pins:

```
attachInterrupt(digitalPinToInterrupt(flow_out_pin), flowOutPulseCounter, FALLING);
attachInterrupt(digitalPinToInterrupt(flow_in_pin), flowInPulseCounter, FALLING);

```

I used the mentioned function to get the interrupt number and changed the name of the ISR. Here comes a different principle, than your firstly intended way: I would let the sensors count in their own ISR and own variables and only calculate the difference to display it. For that we need to define our 2 ISRs:

```
void flowOutPulseCounter()
{
    flowOutPulseCount++;
}
void flowInPulseCounter()
{
    flowInPulseCount++;
}

```

The count variables of course need to be defined (globally at the top of the sketch):

```
volatile byte flowOutPulseCount = 0;
volatile byte flowInPulseCount = 0;

```

Now we have left the code in `loop()`, which calculates flowrate, fill level and such and displays them. First: When handling interrupt data in the main code, you want to absolutely minimize the time spend with the interrupts deactivated (since in that time you might miss pulses and thus introduce errors). Normally you would just copy the data into local variables, turn on the interrupts again and do the calculation with the local variables. Something like this (inside the `millis()` if statement):

```
// Detach interrupts
detachInterrupt(digitalPinToInterrupt(flow_out_pin));
detachInterrupt(digitalPinToInterrupt(flow_in_pin));

// copy pulse count variables
byte local_flow_out_count = flowOutPulseCount;
byte local_flow_in_count  = flowInPulseCount;

// reset pulse counter variables
flowOutPulseCount = 0;
flowInPulseCount = 0;

// Reattach interrupts
attachInterrupt(digitalPinToInterrupt(flow_out_pin), flowOutPulseCounter, FALLING);
attachInterrupt(digitalPinToInterrupt(flow_in_pin), flowInPulseCounter, FALLING);

// Do calculations using above local variables and display the results
...

```

For the calculations you would then calculate a flow rate and the total flow from each pulse count. With that you can then calculate the total net flow and the fill level.

Note: You might wanna change the variable type for the counters to `unsigned int` to get a greater margin, before they overflow, since that would mean incorrect results and it doesn't hurt you to use it.

# Answer
> 0 votes
As chrisl already provided a very good answer, I am just adding some notes here to complement it.

The variable `pulseCount` is only 8-bits. It will overflow if the flow rate gets above 33.7 L/min. If the possibility exists that the actual flow exceeds this rate, then, as pointed out in chrisl's answer, you should use a 16-bit counter. If, on the other hand, you are sure that this value cannot be exceeded, then you can keep an 8-bit counter, and benefit from the fact that accesses to 8-bit values are *atomic*. This means you do not need to ever disable interrupts:

```
// In global scope:
byte oldPulseCount;

// Within loop(), once per second:
byte newPulseCount = pulseCount;  // atomic read
byte pulseCountDifference = newPulseCount - oldPulseCount;
oldPulseCount = newPulseCount;  // save current value

```

then you compute the flow rate from `pulseCountDifference`. Note that overflows of `pulseCount` are harmless, as the difference `newPulseCount - oldPulseCount` wraps modulo 256 to the correct value. Note also that `pulseCount` is never reset, as doing so could lead to miscounting whenever an interrupt fires after `pulseCount` is read but before it is reset.

> ```
> // Note the time this processing pass was executed. Note that because
> // we've disabled interrupts the millis() function won't actually be
> // incrementing right at this point, but it will still return the value
> // it was set to just before interrupts went away.
> oldTime = millis();
>
> ```

This comment is wrong. The statement `detachInterrupt(sensorInterrupt)` disables *only* an external interrupt. It does not disable interrupts globally, and specifically does not disable the timer interrupt that increments `millis()`. There is therefore no guarantee that the various calls to `millis()` will return the same value within one iteration. Instead, `millis()` should be called only once, and its value remembered:

```
void loop()
{
    unsigned long now = millis();  // save this value
    if (now - oldTime >= 1000) {
        // ...
        oldTime = now;
    }
}

```

Note that I use `>=` for checking the delay: with the `>` operator the period is at least 1001 ms.

> ```
> flowMilliLitres = (flowRate / 60) * 1000;
>
> ```

This is incorrect. It should be

```
flowMilliLitres = (flowRate / 60) * (now - oldTime);

```

for the same reason that `now - oldTime` is used in the computation of `flowRate`. It may be noted that this can be simplified to

```
flowMilliLitres = (1e3/calibrationFactor/60) * pulseCountDifference;

```

as the factors `now - oldTime` cancel out.

---
Tags: code-review
---


# Question
Title: Why echo "R" > /dev/ttyUSB0 doesn't work, but on the same PC Serial Monitor in Arduino IDE works?
I have a strange problem. I am running Ubuntu and NodeMCU si plugged into USB. I have very simple sketch running on it, when it reads letter "R" on serial, it turns ON relay.

When I open Serial Monitor in Arduino IDE and I type letter "R" and send it, it works perfectly. However when I run commands below, it does nothing:

```
stty -F /dev/ttyUSB0 115200
echo "R" > /dev/ttyUSB0

```

I tried running the same commands on different PC with Ubuntu and these system commands work just fine.

I also tried copying exact same configuration from `stty -a -F /dev/ttyUSB` from PC where it works to PC where it doesn't, but it didn't help either.

I don't think it's driver issue, because if it would, then I suppose it wouldn't work with Serial Monitor also.

Thank you for any help or hints in advance.

# Answer
OK, so I resolved this problem, but only half-way. I was using NodeMCU with CH340 ... and this controller worked only in Serial Monitor, not in command shell on one computer (it worked fine on other computer).

So I tried using different NodeMCU with CP2102 and it worked just fine. So I assume there must be some kind of issue with ch341 driver in my linux, I don't know.
> 0 votes

# Answer
I had the same issue. After entering command that Majenko suggested:

```
stty -F /dev/ttyUSB0 -hupcl

```

I still wasn't able to send commands to Arduino nano. Strangely, when I open Arduino IDE Serial Monitor and send command it works. When I close it, I can send commands in terminal to Arduino for some time. Then it stops working again :/
> 2 votes

---
Tags: serial, nodemcu, linux
---


# Question
Title: Help On Creating Derived classes in Headers
Here's a small problem I encountered while I was trying to make this small header file `Devices.h`:

> Is it possible to use templates with abstract classes ? If yes, how and how can I use that abstract class to derive another class ?

Here's the contents of the header file :

```
#ifndef Devices_h
#define Devices_h

/* Initial build for MCUOS
Anybody can edit this according to their device needs */

#include "Arduino.h"

template < typename datatype>

class Device_Handler
{
    // a class to handle devices
    public:
        virtual void write_to_device(datatype *send_data)= 0; // write data to device
        virtual void read_from_device(datatype *store_location)= 0 ; // read data from device to location
        virtual void clear_device() = 0; // clear device state
};

class Serial_Handler:public Device_Handler<char*>
{
   public:
          void write_to_device(char *send_data);
          void read_from_device(char *store_location);
          void clear_device();
};

void Serial_Handler<char*>::write_to_device(char *send_data){
        Serial.println(*send_data);
 }

void Serial_Handler<char*>::read_from_device(char *store_location){
       *store_location = Serial.read();
}

void Serial_Handler::clear_device(){
        Serial.flush();
}

#endif

```

This is a small project I am trying at home nowadays (that MCUOS thing up there), also considering it a learning opportunity. I am not sure if I wrote the code in the header the right way. Initially, I made the `Device_Handler` class and used it in my sketch to craft the `Serial_Handler` class, but then it showed an error that the compiler expected a class name before the '{' character right at the place where I started writing the code for the derived class. Thus I decided to move the code for the derived class to the header, but I decided to seek your advice before heading further as I fear that more errors may come up and as I am kind of a beginner at C++.

Thanks in advance !

EDIT : I also doubt if it was because I wrote a comment near the starting line of the abstract class as the syntax highlighter here showed the comments in colour.

**Edit**: I resolved the issue up there (it was due to the misplaced comment), but a new issue has popped up saying that it expected an initialiser before the '\<' token at the places where I had defined the functions in the derived class. This is where my actual is.

My snippets of main concern:

```
void Serial_Handler<char>::write_to_device(char *send_data){
        Serial.println(*send_data);
 }

void Serial_Handler<char*>::read_from_device(char *store_location){
       *store_location = Serial.read();
}

```

I doubt if these will be able to handle long sentences or have syntax errors.

**Edit** I decided to move forward despite errors. Here's how I remade my header file:

```
#ifndef Devices_h
#define Devices_h

/* Initial build for MCUOS
Anybody can edit this according to their device needs */

#include "Arduino.h"

template < typename datatype>
class Device_Handler
{
               // a class to handle devices
    public:
        virtual void write_to_device(datatype *send_data)= 0; // write data to device
        virtual void read_from_device(datatype *store_location)= 0 ; // read data from device to location
        virtual void clear_device() = 0; // clear device state
};

class Serial_Handler:public Device_Handler<char*>
{
   public:
          void write_to_device(char *send_data);
          void read_from_device(char *store_location);
          void clear_device();
};

void Serial_Handler::write_to_device(char *send_data){
        Serial.println(*send_data);
 }

void Serial_Handler::read_from_device(char *store_location){
       *store_location = Serial.read();
}

void  Serial_Handler::clear_device(){
        Serial.flush();
}

#endif

```

Here's the sketch code:

```
#include <Devices.h>

Serial_Handler myserial;
char storage = '\0';
char test_string[] = "Hello";

void setup() {
  Serial.begin(9600);
  myserial.write_to_device(test_string);
  myserial.read_from_device(&storage);
}

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

}

```

(I know that the code up there may also be faulty) and errors come up:

```
Arduino: 1.8.13 (Windows 10), Board: "Arduino Uno"
Devices_Test:3:16: error: cannot declare variable 'myserial' to be of abstract type 'Serial_Handler'

 Serial_Handler myserial;

                ^~~~~~~~

In file included from C:\Users\<smbdy>\Documents\Arduino\Devices_Test\Devices_Test.ino:1:0:

C:\Users\<smbdy>\Documents\Arduino\libraries\Devices/Devices.h:19:7: note:   because the following virtual functions are pure within 'Serial_Handler':

 class Serial_Handler:public Device_Handler<char*>

       ^~~~~~~~~~~~~~

C:\Users\<smbdy>\Documents\Arduino\libraries\Devices/Devices.h:14:16: note:     void Device_Handler<datatype>::write_to_device(datatype*) [with datatype = char*]

   virtual void write_to_device(datatype *send_data)= 0; // write data to device

                ^~~~~~~~~~~~~~~

C:\Users\<smbdy>\Documents\Arduino\libraries\Devices/Devices.h:15:16: note:     void Device_Handler<datatype>::read_from_device(datatype*) [with datatype = char*]

   virtual void read_from_device(datatype *store_location)= 0 ; // read data from device to location

                ^~~~~~~~~~~~~~~~

exit status 1

cannot declare variable 'myserial' to be of abstract type 'Serial_Handler'

```

How should I resolve this?

# Answer
> 1 votes
You are on the track, but it needs some adjustments:

```
template < typename datatype>
class Device_Handler
{
    // a class to handle devices
    public:
        virtual void write_to_device(datatype *send_data)= 0; // write data to device
        virtual void read_from_device(datatype *store_location)= 0 ; // read data from device to location
        virtual void clear_device() = 0; // clear device state
};

class Serial_Handler:public Device_Handler<char> // instead of char*
{
   public:
       void write_to_device(char *send_data) override;
       void read_from_device(char *store_location) override;
       void clear_device() override;
};

void Serial_Handler::write_to_device(char *send_data){ // It's not template, so no template specialization
        Serial.println(*send_data);
 }

void Serial_Handler::read_from_device(char *store_location){
       *store_location = Serial.read();
}

void Serial_Handler::clear_device(){
        Serial.flush();
}

```

The alternative is:

```
template < typename datatype>
class Device_Handler
{
    // a class to handle devices
    public:
        virtual void write_to_device(datatype send_data)= 0; // write data to device
        virtual void read_from_device(datatype store_location)= 0 ; // read data from device to location
        virtual void clear_device() = 0; // clear device state
};

class Serial_Handler:public Device_Handler<char*>
{
   public:
       void write_to_device(char *send_data) override;
       void read_from_device(char *store_location) override;
       void clear_device() override;
};

```

---
Tags: arduino-uno, c++
---


# Question
Title: How to declare char array[] using integers?
Can anyone please tell me how to declare a char variable using a few integers?

I need to declare a byte information for `shiftOut()` function as char.

```
int a = 0;
int b = 1;
int c = 0;
int d = 1;
int e = 1;
int f = 0;
int e = 0;
int f = 1;

char information[] = {"B" + a + b + c + d + e + f};

void setup() {
  Serial.println(information);
}

void loop() {
  shiftOut(pin, pin, MSBFIRST, information);
}

```

In command `Serial.println(information);` I want to get back `B01011001`

Now the output I am getting `⸮⸮`

Of course the simpliest way to create that will be:

`char information[] = "B01011001";`

But I need to change the individual bits in `int bit =` variable.

Please note that substition `int bit =` with `char bit =` is unable for my code, using int of value of individual bits is necessarily. Because I am using my project with blynk, and there is function `a = param.asInt();` , `param.asChar();` does not exist.

How to do that?

Thank you for responses!

# Answer
I think you are getting something wrong about `shiftOut()`. It will transfer exactly 1 byte (or 1 `char`). It does not take an array as parameter. I guess you want to write the 8 bits, that you are defining with your `int`s, as one byte out. Defining at byte directly would look like this:

```
byte information = 0b00101100;

```

The `0b` tells the compiler, that the following number is encoded in binary. So you have one single byte, that contains all your information (all the bits). Then you can do

```
shiftOut(data_pin, clock_pin, MSBFIRST, information);

```

(Please note, that the data\_pin and the clock pin need to be different).

If you want to print the `information` variable to Serial, showing the binary representation, you can use the corresponding parameter of the `print()` function.

```
Serial.print(information, BIN);

```

Will print the binary representation (zeros and ones as text) of the variable. So, to get "B1011001", you would do:

```
Serial.print("B");
Serial.println(information, BIN);

```

Note, that the `print()`/`println()` function will remove all leading zeros.

---

How to put the `information` byte with your `int`s? Each of them is either zero or one and represents one bit. So you can use the bitwise operators to put them together:

```
information = (a << 7) | (b << 6) | (c << 5) | (d << 4) | (e << 3) | (f << 2) | (g << 1) | h;

```

For each `int` only the first (Least significant) bit is important, since the others are always zero (because the int can be only one or zero). So we shift the `int` value to the left by the number of the corresponding bit minus 1 (so shifting `a` 7 places to the left to put its least significant bit to the most significant bit of `information`. We are doing that for all our `int` values. Then we put them all together into one byte by using the `|` (bitwise OR) operator.

**Note:** We don't know, where these `int`s are coming from. Even when stating, that you absolutely need those `int`s, you could organize them in an array instead of single variables. That would look like this:

```
int int_data[8] = {0, 0, 1, 0, 1, 1, 0, 0};
...
// in a function (like loop() or setup())
byte information = 0;
for(int i=0;i<8;i++) information |= int_data[7-i] << i;

```

It's up to you, if you want to do that.
> 1 votes

---
Tags: shift-register
---


title: Serial and I2C not working together

text:
# Question
Title: Serial and I2C not working together
I have very peculier problem. When I run this code SSD1306 fails to initialize. Output at serial console is: 20:26:33.194 -\> MPU6050 OLED demo

20:26:33.532 -\> SSD1306 allocation failed

```
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_MPU6050.h>
#include <Adafruit_SSD1306.h>
#include <Adafruit_Sensor.h>

#define SCREEN_WIDTH 128 // OLED display width, in pixels
#define SCREEN_HEIGHT 64 // OLED display height, in pixels
#define OLED_RESET     4 // Reset pin # (or -1 if sharing Arduino reset pin)
#define SCREEN_ADDRESS 0x3D ///< See datasheet for Address; 0x3D for 128x64, 0x3C for 128x32

Adafruit_MPU6050 mpu;
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);

int count =0;

void setup() {

  Serial.begin(9600);
  while (!Serial);
  Serial.println("MPU6050 OLED demo");

  if (!mpu.begin()) {
    Serial.println("Sensor init failed");
    while (1)
      yield();
  }
  Serial.println("Found a MPU-6050 sensor");

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

  display.display();
  delay(500); // Pause for 2 seconds
  display.setTextSize(1);
  display.setTextColor(WHITE);
  display.setRotation(0);
}

void loop() {
  sensors_event_t a, g, temp;
  mpu.getEvent(&a, &g, &temp);

  display.clearDisplay();
  display.setCursor(0, 0);

  display.println("Accelerometer - m/s^2");
  display.print(a.acceleration.x, 1);
  display.print(", ");
  display.print(a.acceleration.y, 1);
  display.print(", ");
  display.print(a.acceleration.z, 1);
  display.println("");

  display.println("Gyroscope - rps");
  display.print(g.gyro.x, 1);
  display.print(", ");
  display.print(g.gyro.y, 1);
  display.print(", ");
  display.print(g.gyro.z, 1);
  display.println("");
  display.display();
  delay(100);
}

```

But when I run this code, without displaying gyro everything runs fine. Adafruit logo is displayed and then followed by regular accelerometer data.

```
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_MPU6050.h>
#include <Adafruit_SSD1306.h>
#include <Adafruit_Sensor.h>

#define SCREEN_WIDTH 128 // OLED display width, in pixels
#define SCREEN_HEIGHT 64 // OLED display height, in pixels
#define OLED_RESET     4 // Reset pin # (or -1 if sharing Arduino reset pin)
#define SCREEN_ADDRESS 0x3D ///< See datasheet for Address; 0x3D for 128x64, 0x3C for 128x32

Adafruit_MPU6050 mpu;
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);

int count =0;

void setup() {

  //Serial.begin(9600);
  //while (!Serial);
  //Serial.println("MPU6050 OLED demo");

  if (!mpu.begin()) {
    //Serial.println("Sensor init failed");
    while (1)
      yield();
  }
  //Serial.println("Found a MPU-6050 sensor");

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

  display.display();
  delay(500); // Pause for 2 seconds
  display.setTextSize(1);
  display.setTextColor(WHITE);
  display.setRotation(0);
}

void loop() {
  sensors_event_t a, g, temp;
  mpu.getEvent(&a, &g, &temp);

  display.clearDisplay();
  display.setCursor(0, 0);

  display.println("Accelerometer - m/s^2");
  display.print(a.acceleration.x, 1);
  display.print(", ");
  display.print(a.acceleration.y, 1);
  display.print(", ");
  display.print(a.acceleration.z, 1);
  display.println("");

  display.println("Gyroscope - rps");
  display.print(g.gyro.x, 1);
  display.print(", ");
  display.print(g.gyro.y, 1);
  display.print(", ");
  display.print(g.gyro.z, 1);
  display.println("");
  display.display();
  delay(100);
}

```

Now, while debugging when I disable Serial logs and comment all Serial.print then the above code runs properly, logo is displayed, accelerometer and gyro both the data are displayed on OLED properly.

Compiler Log for non-working code is: Sketch uses 21980 bytes (71%) of program storage space. Maximum is 30720 bytes. Global variables use 761 bytes (37%) of dynamic memory, leaving 1287 bytes for local variables. Maximum is 2048 bytes.

The setup I am using as Arduino Nano, MPU6050 connected over I2C (address 0x68), SSD1306 based 0.96" 128x64 display over I2C (address 0x3D). I am using A4 and A5 pin of Arduino Nano as I2C. Both device are connected over same bus. I am using breadboard for testing.

PS: Both the code compiles without error or warning

# Answer
> 3 votes
The SSD1306 uses a *lot* of RAM. Pretty much all your RAM. Serial also uses quite a bit of RAM. The two struggle to work together.

There is a special "text only" SSD1306 library that uses considerably less RAM: https://github.com/greiman/SSD1306Ascii

# Answer
> 1 votes
Thank you Majenko...

It was low RAM problem. SSD1306 takes 1K, with MPU6050 the and serial print which I have included the remaining RAM is 5 bytes only, hence the initialization issue. I followed simple guideline to reduce RAM footprint

Read this thread https://stackoverflow.com/questions/8649174/checking-memory-footprint-in-arduino

Code to print available SRAM.

```
Serial.print(availableMemory());

// free RAM check for debugging. SRAM for ATmega328p = 2048Kb.
int availableMemory() {
    // Use 1024 with ATmega168
    int size = 2048;
    byte *buf;
    while ((buf = (byte *) malloc(--size)) == NULL);
        free(buf);
    return size;
}

```

---
Tags: serial, i2c, mpu6050, oled
---


title: How do I pause a loop just once?

text:
# Question
Title: How do I pause a loop just once?
I´m trying to make a pause in a loop, but just for the first time it loops. The next loops i would like the program to NOT do the pause. Just once time, each time a button is pressed. Does anybody knows how to do it? Thanks! This is the code i want to pause just once:

```
void loop() {
  if(digitalRead(switch_pin) == LOW){
    digitalWrite(led_green_pin,LOW);
    digitalWrite(led_red_pin,HIGH);
    lastMotionState    = currentMotionState;
    currentMotionState = digitalRead(MOTION_SENSOR_PIN); //
      if (currentMotionState == LOW && lastMotionState == HIGH) {
      servo.write(90);
      }
      else
      if (currentMotionState == HIGH && lastMotionState == LOW) { // pin state change: HIGH -> LOW
      servo.write(0);
      }
  }

```

# Answer
The following code will pause (Give some delay) when it runs for the first time and also when you press the button.

```

void loop() {
  static int status = true;
  if(status){
    //Pause
    delay(15);
    status=false;
    return;
  }

  if(digitalRead(switch_pin) == LOW){
    digitalWrite(led_green_pin,LOW);
    digitalWrite(led_red_pin,HIGH);
    lastMotionState    = currentMotionState;
    currentMotionState = digitalRead(MOTION_SENSOR_PIN); //
      if (currentMotionState == LOW && lastMotionState == HIGH) {
        servo.write(90);
      }
      else if (currentMotionState == HIGH && lastMotionState == LOW) { // pin state change: HIGH -> LOW
        servo.write(0);
      }
  }
  else{
    status = true;
  }
}

```

Give delay according to your need.
> 4 votes

# Answer
This is pretty simple, although you shouldn't see any difference, because `loop()` is running a lots of times in one second. But:

```
bool firstrun = true;
void loop() {
  if(firstrun == true){};
  else{
    if(digitalRead(switch_pin) == LOW){
      digitalWrite(led_green_pin,LOW);
      digitalWrite(led_red_pin,HIGH);
      lastMotionState    = currentMotionState;
      currentMotionState = digitalRead(MOTION_SENSOR_PIN); //
        if (currentMotionState == LOW && lastMotionState == HIGH) {
          servo.write(90);
        }
        else if (currentMotionState == HIGH && lastMotionState == LOW) { // pin state change: HIGH -> LOW
          servo.write(0);
        }
    }
  }
  firstrun = false;
}

```
> 0 votes

---
Tags: arduino-uno, c++, loop
---


# Question
Title: How to use float data from a sensor with the Arduino mouse library
I'm using a gyroscope, which returns angular velocity in floats. I'm trying to use this data with the arduino mouse library. The move function requires a signed character. I'm not what the best way is to convert the `float` data from the sensor into `signed char`.

In what way can I do this, losing the least in terms of precision?

I found out you can use `dtostrf` to transfer floats into an array of characters, but not sure what to do following this or if it's even the best way.

I would appreciate any guidance.

# Answer
The mouse library expects the movement coordinates to be provided as 8-bit signed integers, which corresponds to the `int8_t` data type. This type is actually an alias to `signed char`, but calling it this way is confusing, as the word `char` somehow implies a type meant to store characters, which is definitely not the case here.

Converting a `float` to any integer type can be done by plain assignment, with two caveats:

* If the float exceeds the range of the integer, the assignment will wrap around modulo 2^(integer size in bits). This is undesirable and can be prevented by first `constrain()`ing the float to the appropriate range.
* The assignment rounds towards zero, whereas rounding to the nearest integer is better if you want to minimize the errors. This can be achieved with the `round()` macro.

In summary:

```
// In global context:
const float scale = 0.4;  // scale factor for mouse moves

// Within loop():
float rotation = get_data_from_gyroscope();
int8_t mouse_move = round(constrain(rotation * scale, -128, +127));

```

Note that the optimal scale can only be determined experimentally: you have to tweak it until your input device “feels” right.
> 1 votes

# Answer
You are misunderstanding the type `char`. It is named character, because in ASCII representation you can use it to save one character. But internally it just is a number. The Arduino doesn't care, if you save characters in it or numbers, because characters are also numbers for it.

A `signed char`, like the `move()` function of the library uses\` has 1 byte and is signed, thus can hold numbers from -128 to 127.

While the documentation is not clear about what the x and y parameters really represent the answer to this question is clear about it. Basically the whole range from -128 to +127 represents a whole inch (or what the computer thinks is an inch). So this results in a resolution of `1" / (127 - -128) = 1" / 255 = 0.0039"` (or about 0.1mm). I don't know, what values you are getting from the sensor, but you will have to scale it to somewhere in the -128 to 127 range (depends on how sensitive you want it to be). And you won't loose precision here. The sensor values most likely are more precise, than the range of the mouse `move()` function.

The calculation will then be as simple as

```
signed char mouse_x = sensor_x * factor + offset;

```

The result of the calculation will implicitly converted to a 1 byte signed integer (this is what `signed char` is). If you want to make it clearer what happens here, you can also write:

```
signed char mouse_x = (signed char)(sensor_x * factor + offset);

```

This is not needed, but you might wanna do it for clarity.

---

Seen in Edgar Bonets answer: You might wanna contrain the value of above calculation to the -128 to 127 range. If you get an unexpected high value from your sensor, the above calculation would overflow the `mouse_x` variable (not good for correct values). So capping the values to that range with the `constrain()` function is definitely good. Refer to Edgars answer and the documentation for this.
> 1 votes

---
Tags: float, convert
---


title: Arduino IDE 2.0 Beta doesn't start

text:
# Question
Title: Arduino IDE 2.0 Beta doesn't start
Yesterday i downloaded the new version of the IDE to take advantage of all the new features, but it just won't open. I tried installing it to different paths, different PC's, i deleted the package\_index.json and the cache folder, but nothing. It stucks in the opening screen (see image below), any other ideas?

# Answer
I have a very slow internet connection and the Arduino IDE seems to depend a lot on it. When I launch it, I shut down internet and it opens in a breeze.
> 1 votes

---
Tags: arduino-ide-2
---


# Question
Title: Programmatically-adjustable buck converter module?
LM2596 is easy to use and cheap, but I have to adjust the output voltage using a screw driver. On the web, there was a "hack" that someone posted, but that hack does not seem as clean or stable as using LM2596 as it is intended to be used, using screw driver. Is there something that is easy-to-use just like LM2596, but has some pins that can be used to dynamically adjust the output voltage using an Arduino?

# Answer
The hack you described is most likely just feeding voltage from filtered PWM signal generated by microcontroller to the feedback loop of LM2596. I think you can get good enough noise performance with this approach if voltage change rate is not a concern. It all comes down to the PWM filter parameters. You can decrease noise by adjusting RC filter parameters (increasing capacitor and resistor values). It will cause increased delay in voltage change, but it will reduce the noise from PWM signal. Also, you can increase the PWM frequency by avoiding standard analogWrite which has pretty low frequency and configuring a separate timer for PWM generation. Alternatively, if you need some specific voltages, you can replace the potentiometer with a fixed value resistor array connected in parallel and connect each resistor though separate low power MOSFET. This way, you can connect and disconnect a specific resistor which will change the total resistance of the array, changing the output voltage. It will only allow changing voltage by steps and the step size is dictated by the number of resistors, but the noise performance will be the same as using a potentiometer.
> 1 votes

---
Tags: voltage, convert
---


# Question
Title: ESP32 FREERTOS crash using Adafruit ST7789 in tasks with the Wifi enabled
I am trying to create a clock using a ST7789 display and a DS3231 RTC. In this clock I want to use NTP to keep it synced and maybe use the WiFi to anything else. My problem started when I have tried to use tasks to split the code into pieces, manage priorities and to keep the loop code as clean as possible. When I try to update the display text from a task the ESP32 just crash and reboots. I have cleaned the code to see where is the problem and I have noticed that the problem comes when I connect to my Router and then I try to update the text in the display, but doesn't fail if the WiFi is not started or I update the text outside the task. The cleaned code I am using is this:

```
#include <WiFi.h>
#include <Adafruit_ST7789.h>

#if CONFIG_FREERTOS_UNICORE
#define ARDUINO_RUNNING_CORE_0 0
#define ARDUINO_RUNNING_CORE_1 0
#else
#define ARDUINO_RUNNING_CORE_0 0
#define ARDUINO_RUNNING_CORE_1 1
#endif

#define TFT_MOSI 23  // SDA Pin on ESP32
#define TFT_SCLK 18  // SCL Pin on ESP32
#define TFT_CS   15  // Chip select control pin
#define TFT_DC    2  // Data Command control pin
#define TFT_RST   4  // Reset pin (could connect to RST pin)

// Colors
#define COLOR_TOP_BG tft.color565(125, 125, 125)
#define COLOR_TL_BG tft.color565(3, 96, 7)
#define COLOR_BL_BG tft.color565(3, 96, 7)
#define COLOR_TR_BG tft.color565(117, 70, 2)
#define COLOR_BR_BG tft.color565(117, 109, 2)

#define COLOR_TOP_TEXT ST77XX_WHITE
#define COLOR_TL_TEXT ST77XX_BLACK
#define COLOR_TL_TEXT ST77XX_BLACK
#define COLOR_TL_TEXT ST77XX_BLACK
#define COLOR_TL_TEXT ST77XX_BLACK

static const char* ssid     = "WIFI_SSID";
static const char* password = "**REDACTED**";

// Initialize Adafruit ST7789 TFT library
Adafruit_ST7789 tft = Adafruit_ST7789(TFT_CS, TFT_DC, TFT_RST);

// the setup function runs once when you press reset or power the board
void setup() {

  // initialize serial communication at 115200 bits per second:
  Serial.begin(115200);

  // Now set up two tasks to run independently.
  xTaskCreate(
    updateDateTime,
    "updateDateTime",   // A name just for humans
    1024,  // This stack size can be checked & adjusted by reading the Stack Highwater
    NULL,
    3,  // Priority, with 3 (configMAX_PRIORITIES - 1) being the highest, and 0 being the lowest.
    NULL
  );

  // Connecting to Wifi
   WiFi.begin(ssid, password);

  tft.init(240, 240, SPI_MODE2);    // Init ST7789 display 135x240 pixel
  tft.setRotation(3);
  drawBackground();
}

void loop() {

}

// Function to draw the display background
void drawBackground() {
  tft.fillScreen(0xFFFFFF);
  tft.fillRect(0, 0, 240, 24, COLOR_TOP_BG);
  tft.fillRect(0, 24, 120, 107, COLOR_TL_BG);
  tft.fillRect(0, 133, 120, 107, COLOR_BL_BG);
  tft.fillRect(120, 24, 120, 107, COLOR_TR_BG);
  tft.fillRect(120, 133, 120, 107, COLOR_BR_BG);

  tft.fillRect(0, 22, 240, 4, ST77XX_BLACK);
  tft.fillRect(0, 130, 240, 3, ST77XX_BLACK);
  tft.fillRect(118, 22, 4, 218, ST77XX_BLACK);
}

// Function to update the date/time
void updateDateTime( void * pvParameters ) {
  for( ;; ) {
    //tft.init(240, 240, SPI_MODE2);
    tft.setTextColor(COLOR_TOP_TEXT, COLOR_TOP_BG);
    tft.setCursor(6, 4);
    tft.println("MIE");

    delay(100);
  }
}

```

If I comment the WiFi.begin function or I call the function from loop without create a task or just move the three lines to loop function, it works perfectly.

```
#include <WiFi.h>
#include <Adafruit_ST7789.h>

#if CONFIG_FREERTOS_UNICORE
#define ARDUINO_RUNNING_CORE_0 0
#define ARDUINO_RUNNING_CORE_1 0
#else
#define ARDUINO_RUNNING_CORE_0 0
#define ARDUINO_RUNNING_CORE_1 1
#endif

#define TFT_MOSI 23  // SDA Pin on ESP32
#define TFT_SCLK 18  // SCL Pin on ESP32
#define TFT_CS   15  // Chip select control pin
#define TFT_DC    2  // Data Command control pin
#define TFT_RST   4  // Reset pin (could connect to RST pin)

// Colors
#define COLOR_TOP_BG tft.color565(125, 125, 125)
#define COLOR_TL_BG tft.color565(3, 96, 7)
#define COLOR_BL_BG tft.color565(3, 96, 7)
#define COLOR_TR_BG tft.color565(117, 70, 2)
#define COLOR_BR_BG tft.color565(117, 109, 2)

#define COLOR_TOP_TEXT ST77XX_WHITE
#define COLOR_TL_TEXT ST77XX_BLACK
#define COLOR_TL_TEXT ST77XX_BLACK
#define COLOR_TL_TEXT ST77XX_BLACK
#define COLOR_TL_TEXT ST77XX_BLACK

static const char* ssid     = "WIFI_SSID";
static const char* password = "**REDACTED**";

// Initialize Adafruit ST7789 TFT library
Adafruit_ST7789 tft = Adafruit_ST7789(TFT_CS, TFT_DC, TFT_RST);

// the setup function runs once when you press reset or power the board
void setup() {

  // initialize serial communication at 115200 bits per second:
  Serial.begin(115200);

  // Connecting to Wifi
   WiFi.begin(ssid, password);

  tft.init(240, 240, SPI_MODE2);    // Init ST7789 display 135x240 pixel
  tft.setRotation(3);
  drawBackground();
}

void loop() {
  void * test;
  updateDateTime(test);
}

// Function to draw the display background
void drawBackground() {
  tft.fillScreen(0xFFFFFF);
  tft.fillRect(0, 0, 240, 24, COLOR_TOP_BG);
  tft.fillRect(0, 24, 120, 107, COLOR_TL_BG);
  tft.fillRect(0, 133, 120, 107, COLOR_BL_BG);
  tft.fillRect(120, 24, 120, 107, COLOR_TR_BG);
  tft.fillRect(120, 133, 120, 107, COLOR_BR_BG);

  tft.fillRect(0, 22, 240, 4, ST77XX_BLACK);
  tft.fillRect(0, 130, 240, 3, ST77XX_BLACK);
  tft.fillRect(118, 22, 4, 218, ST77XX_BLACK);
}

// Function to update the date/time
void updateDateTime( void * pvParameters ) {
  for( ;; ) {
    //tft.init(240, 240, SPI_MODE2);
    tft.setTextColor(COLOR_TOP_TEXT, COLOR_TOP_BG);
    tft.setCursor(6, 4);
    tft.println("MIE");

    delay(100);
  }
}

```

I am starting with FREERTOS and ESP32, and I am not sure what I am doing wrong... I have thougth that the problem was the RTC but after remove the RTC code and see that was the WiFi, I am not sure what can be the problem.

Best regards and thanks.

# Answer
To pin the function to a core was not working for me surely because the init code is outside the function, so I have moved the init code to inside the function, out of the loop:

```
#include <WiFi.h>
#include <Adafruit_ST7789.h>

#if CONFIG_FREERTOS_UNICORE
#define ARDUINO_RUNNING_CORE_0 0
#define ARDUINO_RUNNING_CORE_1 0
#else
#define ARDUINO_RUNNING_CORE_0 0
#define ARDUINO_RUNNING_CORE_1 1
#endif

#define TFT_MOSI 23  // SDA Pin on ESP32
#define TFT_SCLK 18  // SCL Pin on ESP32
#define TFT_CS   15  // Chip select control pin
#define TFT_DC    2  // Data Command control pin
#define TFT_RST   4  // Reset pin (could connect to RST pin)

// Colors
#define COLOR_TOP_BG tft.color565(125, 125, 125)
#define COLOR_TL_BG tft.color565(3, 96, 7)
#define COLOR_BL_BG tft.color565(3, 96, 7)
#define COLOR_TR_BG tft.color565(117, 70, 2)
#define COLOR_BR_BG tft.color565(117, 109, 2)

#define COLOR_TOP_TEXT ST77XX_WHITE
#define COLOR_TL_TEXT ST77XX_BLACK
#define COLOR_TL_TEXT ST77XX_BLACK
#define COLOR_TL_TEXT ST77XX_BLACK
#define COLOR_TL_TEXT ST77XX_BLACK

static const char* ssid     = "MOVISTAR_F6112";
static const char* password = "C89qlqMifsjDMWhbdsJQ";

// Initialize Adafruit ST7789 TFT library
Adafruit_ST7789 tft = Adafruit_ST7789(TFT_CS, TFT_DC, TFT_RST);

// the setup function runs once when you press reset or power the board
void setup() {

  // initialize serial communication at 115200 bits per second:
  Serial.begin(115200);

  xTaskCreatePinnedToCore(
    updateDateTime,   /* Function to implement the task */
    "updateDateTime", /* Name of the task */
    1024,      /* Stack size in words */
    NULL,       /* Task input parameter */
    3,          /* Priority of the task */
    NULL,       /* Task handle. */
    0
  );

  // Connecting to Wifi
   WiFi.begin(ssid, password);

  //tft.init(240, 240, SPI_MODE2);    // Init ST7789 display 135x240 pixel
//  tft.setRotation(3);
//  drawBackground();
}

void loop() {
}

// Function to draw the display background
void drawBackground() {
  tft.fillScreen(0xFFFFFF);
  tft.fillRect(0, 0, 240, 24, COLOR_TOP_BG);
  tft.fillRect(0, 24, 120, 107, COLOR_TL_BG);
  tft.fillRect(0, 133, 120, 107, COLOR_BL_BG);
  tft.fillRect(120, 24, 120, 107, COLOR_TR_BG);
  tft.fillRect(120, 133, 120, 107, COLOR_BR_BG);

  tft.fillRect(0, 22, 240, 4, ST77XX_BLACK);
  tft.fillRect(0, 130, 240, 3, ST77XX_BLACK);
  tft.fillRect(118, 22, 4, 218, ST77XX_BLACK);
}

// Function to update the date/time
void updateDateTime( void * pvParameters ) {
  tft.init(240, 240, SPI_MODE2);
  tft.setRotation(3);
  drawBackground();

  for( ;; ) {
    //tft.init(240, 240, SPI_MODE2);
    tft.setTextColor(COLOR_TOP_TEXT, COLOR_TOP_BG);
    tft.setCursor(6, 4);
    tft.println("MIE");

    delay(100);
  }
}

```

I have kept the function pinned to a core to avoid problems if RTOS decides to run the function on another core later. I have to do more tests, but seems to works.

Best regards.
> 0 votes

---
Tags: wifi, esp32, display
---


# Question
Title: Best way to add external power supply when main PSU is a solar charge controller?
I have a 12V 20A Solar Charge Controller (which is part of my existing Solar Panel System Setup connected to a 12V Sealed Lead Acid Battery) that I will use to power up some pumps with the help of relays and some sensors. And because its a solar charge controller, the output varies depending on the sun, from 12.1v to 13.8v (I set the Load Reconnect, Load Disconnect, Float Charge etc which technically 12V to 13.8V)

How do I power my Arduino Mega safely in this case?

I am planning on using a separate buck converter that will give my Arduino a fixed 9V from the Solar Charge Controller.

Should I power the Arduino with the buck converter parallel to the same PSU (the 12V 20A Solar Charge Controller) I'm using for the pumps and is it safe that way?

or

Should I use a 9V battery to separately power the Arduino Mega? and what is the explanation behind the concept of using an external PSU for the Arduino Mega when the total Amperes all in all is not exceeding the limit 20A at all?

# Answer
> Should I power the Arduino with the buck converter parallel to the same PSU (the 12V 20A Solar Charge Controller) I'm using for the pumps

Yes. However I wouldn't use a 9V buck regulator, but a 5V one and feed it to the 5V pin. That way you bypass the wasteful LDO on the Arduino, and when running from solar every bit of power saving you can muster helps.

> and is it safe that way?

Yes, it's safe. As long as the buck regulator you are using is rated for the voltages in question.
> 4 votes

# Answer
Ok first, you need a battery for all this to work. The solar charge controller won't drive into nothin', that is not what they are designed to do.

Its full name is "solar *battery* charge controller". Size the battery any way you like, just make sure the charge controller knows what kind it is, so it sets the proper charge curves and doesn't overcharge it/boil it dry/make it catch fire (lithium).

Once you have a battery in the system, paralleling in another battery charger is not a problem, be it wind, AC mains, or another solar CC.

---

Now, you will need to manage the case where the Arduino calls for the pump to turn on, but the solar panel is not making enough power to successfully power the pump. This will not magically sort itself out.

* If you did not have a battery, it'll "crow bar". The pump would effectively pull the solar voltage to near zero, which would cause the Arduino to shut down, turning off the pump and causing solar voltage to recover. The Arduino would reboot, try again, and fail again. Repeating. So a crow-bar condition.
* If you do have a battery, then the Arduino will successfully spin up the pump, *but*, the solar won't be enough and this will be depleting the battery. If your usage runs the battery flat, see crow-bar above.
* If you have a battery and the Arduino monitors battery voltage, it can defer operation until the Arduino knows the battery is sufficiently charged for the work needed. At this point you don't need to care if the solar is up, the battery will carry the "buffer". Make sure to shut the load off before the battery is depleted enough to create a crow-bar condition.

Note that if the battery is lead-acid, it should be managed to stay within 60-100% state of charge. Depleting a lead-acid below 60% of max will rapidly age the battery. It probably will be, since they are a happy intersection of "cheap" and "well-supported by every charge controller ever made".

Power to the Arduino itself should be taken as close as possible to the energy source (e.g. battery) — *even if that means a long, redundant cable, **especially** in that case actually*. Do not share a supply cable with motors or pumps or other heavy loads!!! I have seen many installations where the startup current of the motor causes enough *voltage drop* down the shared supply cable to cause the Arduino to lose power and reboot. That is quickly cured by running a redundant V+ and V- power cable just for the Arduino.
> 0 votes

---
Tags: power, electronics, electricity, solar
---


title: How to use digital pin as ground?

text:
# Question
Title: How to use digital pin as ground?
I have recently brought an arduino nano. It has only two ground pins but I needed three for my project. Is there a way to use a digital or analog pin as ground pin? Please show me how to do it

# Answer
> 5 votes
If your project is on a breadboard, you can use one of the "rails", typically the blue longways row at either edge of the breadboard, to collect all of the necessary grounds, and wire that to one Ground pin on the Arduino.

If you're building a printed circuit board to connect to the Arduino, do the same thing - collect all of the PCB grounds together and wire that to one Arduino Ground pin.

If you're using a manufactured shield, you may have to get creative about collecting your grounds. A tiny breadboard is one way. Another is to solder a number of wires together in star-formation, insulate the solder joint with tape or shrink-tube, and connect one of the star's points to the Arduino ground.

*If* some of your devices needing grounds are low-current devices such as LEDs, you could set an unused pin to OUTPUT mode, and LOW, and use it as a ground, but the device must not be passing more current than an Arduino pin driver can sink. From Atmel's data sheet for the AtMega328p (used in the Uno):

> Although each I/O port can sink more than the test conditions (20mA at VCC = 5V, 10mA at VCC = 3V) under steady state conditions (non-transient), the following must be observed:
>
> ATmega48A/PA/88A/PA/168A/PA/328/P: 1\] The sum of all IOL, for ports C0 - C5, ADC7, ADC6 should not exceed 100mA.
>
> 2\] The sum of all IOL, for ports B0 - B5, D5 - D7, XTAL1, XTAL2 should not exceed 100mA.
>
> 3\] The sum of all IOL, for ports D0 - D4, RESET should not exceed 100mA.
>
> If IOL exceeds the test condition, VOL may exceed the related specification. Pins are not guaranteed to sink current greater than the listed test condition.

# Answer
> 4 votes
There is no need to separate grounds, you can connect all grounds together. In fact they are connected together on the board itself.

# Answer
> 1 votes
You can just try converting two digital pins as 5V VCC and ground. This will be useful when we use multiple sensors.

```
#define VCC2  5 // define pin 5 or any other digial pin here as VCC2
#define GND2  2 // define pin 2 or any other digital pin as Ground 2

void setup() {
  pinMode(VCC2,OUTPUT);//define a digital pin as output
  digitalWrite(VCC2, HIGH);// set the above pin as HIGH so it acts as 5V

  pinMode(GND2,OUTPUT);//define a digital pin as output
  digitalWrite(GND2, LOW);// set the above pin as LOW so it acts as Ground
}

void loop() {
}

```

---
Tags: arduino-nano
---


# Question
Title: Multiple Wire.write() not working for Arduino Nano I2C
## Code for Master

```
#include <Wire.h>

void setup()
{
  Wire.begin();

  Serial.begin(9600);
}

void loop()
{
    Wire.beginTransmission(9);

    Wire.write('c');
    Serial.println('c');
    Wire.write('a');
    Serial.println('a');
    Wire.endTransmission();
}

```

---

In my case `Wire.write('c')` is performing the task which is assigned to `'c'` in slave board. Then its printing `'c'` in serial monitor as intended. But, `Wire.write('a')` line is being neglected and nothing happens on slave board. But again, it's printing `'a'` in serial monitor as per code. Why is that `Wire.write('a');` is neglected? Both boards are Arduino Nano.

## Code for Slave

```
#include <Wire.h>
#define RED 8
#define GREEN 10
int x = 0;

void setup() {
  pinMode (RED, OUTPUT);
  pinMode (GREEN, OUTPUT);
  Wire.begin(9);
  Wire.onReceive(receiveEvent);
}

void receiveEvent(int bytes) {
  x = Wire.read();    // read one character from the I2C
}

void loop() {
    if (x == 'a') {
        digitalWrite(RED, HIGH);
        digitalWrite(GREEN, LOW);
    }
    if (x == 'b') {
        digitalWrite(RED, LOW);
        digitalWrite(GREEN, HIGH);
    }
    if (x == 'c') {
        digitalWrite(RED, HIGH);
        digitalWrite(GREEN, HIGH);
    }
    if (x == 'd') {
        digitalWrite(RED, LOW);
        digitalWrite(GREEN, LOW);
    }
}

```

# Answer
**Important information:** `Wire.write()` does NOT send anything over the I2C lines. It just puts the data into the libraries internal buffer. The actual transmission is then done by `Wire.endTransmission()`.

I2C is packaged transmission protocol. That means, that the transmission is done in confined data packages. In your master code you are calling `Wire.write()` two times before `Wire.endTransmission()`. That means you are sending 1 package with 2 data bytes in it.

Now for your slave code: You are using a callback function for the `onReceive` event. This callback function is called once per transmission. In there you can read all the data of that transmission. After that the data is thrown away (I think actually it gets deleted, when a new transmission is received). You are only reading once with `Wire.read()`. So you only ever read the first byte of every transmission, which is always the letter `'c'`.

**What to do know?** This depends on how you want the code to behave. Since you are setting 2 LEDs based on the received byte it would be better to only send 1 byte transmissions. For that, you can change your master code. For example like this:

```
#include <Wire.h>

void setup()
{
  Wire.begin();

  Serial.begin(9600);
}

void loop()
{
    // Send the command c
    Wire.beginTransmission(9);
    Wire.write('c');
    Wire.endTransmission();

    // Wait 1s, so that we can see the LEDs state accordingly
    delay(1000);

    // Send command a
    Wire.beginTransmission(9);
    Wire.write('a');
    Wire.endTransmission();

    // Wait 1s, so that we can see the LEDs state accordingly
    delay(1000);
}

```

This code will change between `'c'` and `'a'` every second. You need a delay there to actually see the LEDs light up. Otherwise they would change too fast for you to see it.

**Note:** Actually you need to declare the variable `x` as `volatile`, because the onReceive callback is called from an ISR. With that keyword you are telling the compiler, that `x` can change at any time (by the ISR of the corresponding I2C interrupt). It might be, that your current code works, because the compiler was smart enough to see that, but in general you should always use `volatile` with every variable, that can change in an ISR. Declaration then looks like this:

```
volatile int x = 0;

```

And to handle the ISR data really correct, you would need to make the usage atomic, because the ISR can happen in the middle of the comparison for the if statements. An `int` is two bytes, so the first byte might be updated and the second byte not. That would corrupt your data. There are two ways to handle that in your case:

* **Make the reading of `x` atomic:** Normally one would turn of the interrupts, read the volatile variables into local variables (as a copy) and then turn the interrupts on again. That way the interrupt cannot corrupt the data in the variable during reading. The further calculation/comparison would then be done with the local variable.
* **Use a single byte as volatile data**: The described problem does not apply to variables, which only use 1 byte (since on the 8bit Arduinos like the Nano the reading of a single byte cannot be interrupted). So just make `x` of type `char` (or `uint8_t` or `byte`).

You should use the second option.
> 7 votes

---
Tags: serial, arduino-nano, i2c, communication, code-review
---