# Question
Title: Arduino esp32 randomly corrupted variable
Every so often my variable gets corrupted. Sometimes it happens several times in a row and other times it doesn't happen in several hits. I put these logs to rule out that any of the operations interfered. But as you can see just between one log and another, the data is dirty.

This runs on an ESP32 with arduino as framework and this procedure comes from a freeRTOS dequeue.

**log:**

```
[D][RC_msgRouterProcessCommand.cpp:60] _cloudRXServiceWorker(): Mensaje desencolado:
 topic: iot/riego/prueba/valvula/1
 payload: {
  "controlRemoto": true,
  "modulo": 11,
  "slot": 1,
  "status": 1
}
[D][RC_msgRouterProcessCommand.cpp:61] _cloudRXServiceWorker(): running on core >>>> 0
[D][RC_msgRouterProcessCommand.cpp:62] _cloudRXServiceWorker(): 1 >>>>>>>>>>>>>>>>>>>>>> {
  "controlRemoto": true,
  "modulo": 11,
  "slot": 1,
  "status": 1
}
[D][RC_msgRouterProcessCommand.cpp:63] _cloudRXServiceWorker(): 1-1 >>>>>>>>>>>>>>>>>>>>>> {
  "controlRemoto": true,
  "modulo": 11,
  "slot": 1,
  "status": 1
}
[D][RC_msgRouterProcessCommand.cpp:64] _cloudRXServiceWorker(): 1-2 >>>>>>>>>>>>>>>>>>>>>> {
  "controlRemoto": true,
  "modulo": 11,
  "slot": 1,
  "status": 1
}
[D][RC_msgRouterProcessCommand.cpp:65] _cloudRXServiceWorker(): 1-3 >>>>>>>>>>>>>>>>>>>>>> ��@)�?
[D][RC_msgRouterProcessCommand.cpp:66] _cloudRXServiceWorker(): 1-4 >>>>>>>>>>>>>>>>>>>>>> ��@)�?
[D][RC_msgRouterProcessCommand.cpp:67] _cloudRXServiceWorker(): 1-5 >>>>>>>>>>>>>>>>>>>>>> ��@)�?
[D][RC_msgRouterProcessCommand.cpp:69] _cloudRXServiceWorker(): 2 >>>>>>>>>>>>>>>>>>>>>> ��@)�?
[D][RC_msgRouterProcessCommand.cpp:71] _cloudRXServiceWorker(): 3 >>>>>>>>>>>>>>>>>>>>>> ��@)�?
[D][RC_msgRouterProcessCommand.cpp:72] _cloudRXServiceWorker(): Item count: 5
[D][RC_msgRouterProcessCommand.cpp:73] _cloudRXServiceWorker(): 4 >>>>>>>>>>>>>>>>>>>>>> �^�?
[D][RC_msgRouterProcessCommand.cpp:76] _cloudRXServiceWorker(): Item @ index 0 : iot
[D][RC_msgRouterProcessCommand.cpp:76] _cloudRXServiceWorker(): Item @ index 1 : riego
[D][RC_msgRouterProcessCommand.cpp:76] _cloudRXServiceWorker(): Item @ index 2 : prueba
[D][RC_msgRouterProcessCommand.cpp:76] _cloudRXServiceWorker(): Item @ index 3 : valvula
[D][RC_msgRouterProcessCommand.cpp:76] _cloudRXServiceWorker(): Item @ index 4 : 1
[D][RC_msgRouterProcessCommand.cpp:78] _cloudRXServiceWorker(): 5 >>>>>>>>>>>>>>>>>>>>>> �^�?
[D][RC_msgRouterProcessCommand.cpp:93] _cloudRXServiceWorker(): CASE: RC_HW_TYPE_VALVULA
[D][RC_msgRouterProcessCommand.cpp:94] _cloudRXServiceWorker(): XXXXXXXXXXXXXXXXXXXXXXXXXXX �^�?
[E][RC_msgRouterProcessCommand.cpp:223] _get_valve_typeByPaylod(): _get_valve_typeByPaylod. deserializeJson Json:
 �^�?
[E][RC_msgRouterProcessCommand.cpp:228] _get_valve_typeByPaylod(): Fallo la deserializacion del json
[E][RC_msgRouterProcessCommand.cpp:229] _get_valve_typeByPaylod(): Error: InvalidInput

```

**code fragment:**

```
void RC_msgRouter::_cloudRXServiceWorker(){
    log_d("iniciando worker cloudRXService running on core >>>> %d",xPortGetCoreID());
    msg_t mensaje;
    while (true)
    {
        if(xQueueReceive(QfromCloud, &mensaje , queueSpeed / portTICK_PERIOD_MS)){
            log_d("Mensaje desencolado:\n topic: %s\n payload: %s", mensaje.topic,mensaje.payload);
            log_d("running on core >>>> %d",xPortGetCoreID());
            log_d("1 >>>>>>>>>>>>>>>>>>>>>> %s",mensaje.payload);
            log_d("1-1 >>>>>>>>>>>>>>>>>>>>>> %s",mensaje.payload);
            log_d("1-2 >>>>>>>>>>>>>>>>>>>>>> %s",mensaje.payload);
            log_d("1-3 >>>>>>>>>>>>>>>>>>>>>> %s",mensaje.payload);
            log_d("1-4 >>>>>>>>>>>>>>>>>>>>>> %s",mensaje.payload);
            log_d("1-5 >>>>>>>>>>>>>>>>>>>>>> %s",mensaje.payload);
            StringSplitter *splitter = new StringSplitter(mensaje.topic, '/', -1);  // new StringSplitter(string_to_split, delimiter, limit)
            log_d("2 >>>>>>>>>>>>>>>>>>>>>> %s",mensaje.payload);
            int itemCount = splitter->getItemCount();
            log_d("3 >>>>>>>>>>>>>>>>>>>>>> %s",mensaje.payload);
            log_d("Item count: %d", itemCount);
            log_d("4 >>>>>>>>>>>>>>>>>>>>>> %s",mensaje.payload);
            for(int i = 0; i < itemCount; i++){
                String item = splitter->getItemAtIndex(i);
                log_d("Item @ index %d : %s", i,item);
            }
            log_d("5 >>>>>>>>>>>>>>>>>>>>>> %s",mensaje.payload);

```

# Answer
The problem was that a task with higher priority interrupts the process. I increased the priority to this task and the problem is solved.

```
xTaskCreatePinnedToCore(_cloudRXServiceTask, "_cloudRXServiceTask", 2048, this, 20, &_cloudRXServiceWorker_handle,0);

```
> 2 votes

---
Tags: c++, esp32
---


# Question
Title: Stepper motor based clock movement with DS3231
I am working on a clock movement that is powered using a stepper motor and the GSM2 driver board. The delay between steps needed to achieve 1 rpm on the second hand works out to 25 ms. In my current setup, I am sending pulses to the driver board using the delay() function. This works reasonably well, although it is not accurate enough for me. To remedy this problem, I ordered a DS3231 RTC module, thinking I could use that to replace delay()/millis(). However, I can't figure out how to achieve millisecond resolution using the RTC. It seems like it should be strait forward given the oscillator on board the RTC is 32kHz. I am new to arduino programming and am out of my comfort zone with this one.

Does anyone know of a way to achieve the 25 ms pulses we need while still retaining the accuracy of the RTC? Is it possible to use the RTC to correct the output produced by the built in delay()/millis() function? How would you then translate that output to pulses sent to the stepper motor driver board?

Internet research produces some mixed results on whether or not this is possible. I have yet to see an example of a clock with millisecond resolution. The theory behind it makes sense, but I don't know where to start.

# Answer
> 1 votes
It is unclear, why you need the high accuracy, and you didn't include your code. So my explanations will be as broad as your question.

"millisecond resolution" is a broad term. Generally you have to consider 2 different errors.

1. The jitter for every `millis()` value
2. clock drifting over time

You can eliminate the second point quite easily using the RTC with the Time library. It uses the RTC as a reference, so that you don't have the clock drifting this much. Though, you would have to use the libraries functions for all time related things, since it does not change the value of `millis()` or it's siblings.

Also, for low differences in the range of a few milliseconds, you should better use `micros()` instead of `millis()` (if you are not using the RTCs functions).

---

> How would you then translate that output to pulses sent to the stepper motor driver board?

It is unclear, why exactly you need "millisecond resolution", and you didn't show us your code. But there are multiple Stepper libraries on the web, for example the standard Stepper library or the AccelStepper library (Accelstepper is more capable, don't know, if you need it). With the AccelStepper libraries you can set a certain speed and target position and then you simply call then `run()` method (haven't looked up the name, but there is definitely a function like that) until the desired position is reached. The method itself will only pulse the stepper, if it is time to do so. So you are freed from doing all the stuff with `millis()`, since the library is doing that for you.

Though the libraries are using the Arduinos internal time: `millis()` and siblings. To change that, you would have to change the library.

# Answer
> 0 votes
Consider a Phase Locked Loop (PLL) to synchronize your 40x 25ms pulses with your 1pps RTC.

If you need 25ms/pulse to get 1rpm, that's 2400ppm or 1pulse/0.025ms=40pps. If you get a 1pps pulse out of the RTC, you can use it to discipline your timing. https://www.romanblack.com/one\_sec.htm is a good reference.

The basic trick is to keep track of the mismatch and run faster when it is slow, and run slower when it is too fast.

Try something like the below, but replace the LED pulse stuff with your stepper code.

```
// pps_pll.ino for https://arduino.stackexchange.com/questions/67699/stepper-motor-based-clock-movement-with-ds3231
//
// Adapting code from https://www.arduino.cc/reference/en/language/functions/external-interrupts/attachinterrupt/
// to do a PPS PLL per https://www.romanblack.com/one_sec.htm

const int pps = 40;
const int pulse_us = 1;
const int pulse_interval = (1000L / pps);
int count = 0; //
int count_at_sync = 0; //
unsigned long next_pulse = 0; //
unsigned long pulse_off = 0;

const byte led_pin = LED_BUILTIN;
const byte interrupt_pin = 2; // Choose pin per https://www.arduino.cc/reference/en/language/functions/external-interrupts/attachinterrupt/
volatile byte state = LOW;

void setup() {
  pinMode(led_pin, OUTPUT);
  pinMode(interrupt_pin, INPUT_PULLUP);
  attachInterrupt(digitalPinToInterrupt(interrupt_pin), sync_ISR, RISING);
}

void loop() {
  unsigned long loop_micros = micros();  // capture start of loop time
  if (loop_micros >= next_pulse) {
    // Schedule pulse
    digitalWrite(led_pin, HIGH);
    next_pulse += pulse_interval ;
    pulse_off = loop_micros + pulse_us; // schedule off time
    // PLL accounting
    count++;
    if (count_at_sync > 0) next_pulse++; // too fast: slow down
    else if (count_at_sync < 0) next_pulse--; // too slow: speed up
  }
  if (state == HIGH && loop_micros >= pulse_off) {
    state = LOW;
  }
  digitalWrite(led_pin, state);
}

void sync_ISR() { // called by 1pps interrupt
  count_at_sync = (count -= pps); // PLL accounting and record synchronization state
}

```

---
Tags: millis, rtc, stepper-motor, ds3231-alarms
---


title: Power to triac dimmer and arduino uno

text:
# Question
Title: Power to triac dimmer and arduino uno
I am building 2 channel triac dimmer to control led strip lights in my pantry. Have 4 channel Krida module (just use two, I guess) and Uno. Have had some success with the triacDimmer library examples, but now realize I'm not sure of my basic approach.

I want to have two light circuits ramp up to a preset light level, then stay on until the power cuts out. My question is this: is it possible to power the Arduino Uno and the AC going into the triac module from the same switch? Will the microcontroller just "start over" every time the power comes on to it - and will the triac be in "off" status without power to its gate?

This is a matter of design, and I'm way out of my depths. I want to power this project, and write the sketch, so that the two circuits fade on to a pre-set level when the power comes on. Is it ok to plan to turn off the lights by just 'pulling the plug?'

Please let me know if this is still not an appropriate question for this forum. I appreciate any help or feedback. Thanks

# Answer
You ask: "is it possible to power the Arduino Uno and the AC going into the triac module from the same switch? Will the microcontroller just "start over" every time the power comes on to it - and will the triac be in "off" status without power to its gate?" Yes you can put a switch in the line that powers the primary side that feeds both the lights and the UNO power supply. The 4 channel Krida module I have does not turn on the lights until I power the optocoupler. I also have one that has a processor on board and it behaves the same way. When you write your code get a 24V transformer and two 24V lamps to debug your project, that way you will not fry yourself. This is how I normally prototype 120 and 240 Volt circuits. I then test it with the mains when it is all assembled and the test equipment disconnected. Remember some best equipment especially bench type has a connection to the earth ground.
> 1 votes

---
Tags: arduino-uno
---


# Question
Title: What are the correct pins for TWAI (CAN) on ESP32?
compared to the microchip's PICs:

pic16f's does not have an onboard CAN peripheral. so you need an SPI - CAN controller (like MCP2515).

some PIC18f's have an onboard CAN controller, and only need a CAN transceiver. In these cases there are exclusive TX and RX pins to be used.

Are there specific pins to be used as a CAN bus on esp32? peripherals like adc, i2c and others need to use specific pins. Does this happen with CAN too?

I'm using the following configuration: 2 ESP32 devboard boards - arduino on PlatformIO Pin 5 as TX and pin 4 as RX (already in the CAN library), 2 Sn65hvd230 transceiver modules

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

I appreciate any help.

# Answer
> 5 votes
> I looked for information about it in the documentation, but I couldn't find it.

Well, some of their documentation says:

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

And that sort of seems to be backed up by their examples that make use of TWAI\_GENERAL\_CONFIG\_DEFAULT to generate a structure with the arguments filling fields that use `gpoi_num_t`.

There is documentation to the GPIO Matrix generally in the ESP32 technical reference. It is described there as follows:

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

(My emphasis in the above).

And also there is a table (Table 25) in Appendix 2 of the ESP32 datasheet for the GPIO matrix.

Many of the small chips, like the PIC16F series ones, have no internal routing for peripherals, except for deciding which of one or two special functions to use rather than GPIO and ADC channels. Most of the of the ATTiny and ATMega series AVR chips that are not in the 0- and 1- series don't. The 1- and 0- series an a few of the older series parts (e.g. ATTiny841) give you a fixed number (usually two) pre-determined destinations to chose from for some peripherals.

This sort of thing gets more flexible as you get into larger chips, but the having that "matrix" feature that lets choose more freely is *comparatively* rare. Some of the Cypress "PSoC" labeled chips have this sort of feature.

# Answer
> 2 votes
When using arduino and the esp32 core, **any pin** can be assigned to the builtin TWAI controller.

If you use the esp32\_can library https://github.com/collin80/esp32\_can you may change the pin assignment in the following file:

C:\Users\USER\Documents\Arduino\libraries\esp32\_can-master\src\esp32\_can.cpp

> //Set these to the proper pin numbers for you board. Set by default to correct for EVTV ESP32-Due
> //rxpin txpin
> ESP32CAN **attribute**((weak)) CAN0(**GPIO\_NUM\_16**, **GPIO\_NUM\_17**) ;

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

---
Tags: esp32, can-bus
---


# Question
Title: Stabilize data from four gyros/accelerometer
I am currently working on a university project. My aim is to get a rough estimate of the posture of a person's back. For this I have built a system that collects the data from 4 MPU6050 at a central service. From there it will be visualised. My first idea was to draw 4 lines and take the roll angles for the angles between the lines. My problem is that the data from the MPU6050s drifts a lot. I have already created calibration data and use a complementary filter on the nodeMCUs that read the data from the MPUs.

I am using the Adafruit\_MPU6050.h lib to connect to the sensors and get data from it. To calculate roll, pitch and yaw I use the following code:

```
  sensors_event_t gyro_1;
  sensors_event_t accel_1;
  mpu_gyro_1->getEvent(&gyro_1);
  mpu_accel_1->getEvent(&accel_1);

  acc_1_angle_x = (atan(accel_1.acceleration.y / sqrt(pow(accel_1.acceleration.x, 2) + pow(accel_1.acceleration.z, 2))) * 180 / PI) - mpu_1_acc_err_x;
  acc_1_angle_y = (atan(-1 * accel_1.acceleration.x / sqrt(pow(accel_1.acceleration.y, 2) + pow(accel_1.acceleration.z, 2))) * 180 / PI) - mpu_1_acc_err_y;

  previousTime = currentTime;
  currentTime = millis();
  elapsedTime = (currentTime - previousTime) / 1000;

  gyro_1_angle_x = gyro_1_angle_x + (gyro_1.gyro.x - mpu_1_gyro_err_x) * elapsedTime; // deg/s * s = deg
  gyro_1_angle_y = gyro_1_angle_y + (gyro_1.gyro.y - mpu_1_gyro_err_y) * elapsedTime;
  yaw_1 = yaw_1 + (gyro_1.gyro.z - mpu_1_gyro_err_z) * elapsedTime;
  roll_1 = 0.96 * gyro_1_angle_x + 0.04 * acc_1_angle_x;
  pitch_1 = 0.96 * gyro_1_angle_y + 0.04 * acc_1_angle_y;

```

How can I make my data more stable? I tried playing with the 0.96 and 0.04 to change the amount of data I use from the gyro but it only got worse.

If you are interested, this is my project github: https://github.com/Trojan13/posture-control

Thanks in advance for your input!

# Answer
Looking at your code, I see the only place where `gyro_1_angle_x` is updated is here:

```
gyro_1_angle_x = gyro_1_angle_x
    + (gyro_1.gyro.x - mpu_1_gyro_err_x) * elapsedTime;

```

This is adding to `gyro_1_angle_x` a quantity that does not depend on `gyro_1_angle_x` itself. This means that, if there is an uncorrected systematic error in the measurement of `gyro_1.gyro.x` (which there always is, as you can never achieve *perfect* calibration), the errors will pile up, leading to an unbounded drift. Then, you estimate the roll angle as

```
roll_1 = 0.96 * gyro_1_angle_x + 0.04 * acc_1_angle_x;

```

The factor 0.96 slightly reduces the amount of drift (by 4%), but does not change the qualitative behavior: `roll_1` is also prone to unbounded drift.

## Suggested approach

My suggestion will be to forget about angles. Using angles to keep track of your device's attitude is a bad idea: the formulas needed to update the angles are complex (and thus easy to get wrong), computationally expensive, and prone to gimbal lock. For tracking the whole attitude, it would be more reasonable to use rotation matrices or, better yet, quaternions.

In your use case, however, you do not need to track the whole attitude. You have no means to reliably track the yaw angle, and you actually do not even care about this angle. You are only interested in the orientation of the device relative to the vertical direction. Thus I suggest you do no even try to track the attitude, and instead just track the vertical direction. This direction is given by the coordinates of the gravity vector in the device's reference frame. Then you just have one vector to track. No angles, no matrices, no quaternions: just a simple vector.

### Using the accelerometers

The accelerometers are sensitive to the gravity, thus you can use their readings as an estimate of the gravity vector, as in the following pseudo-code:

```
at each time step:
    (accel, gyro) = read_MPU();
    gravity = accel;

```

This may give you the opposite of the gravity (direction of the zenith). That's fine, as long as you know which vector you are tracking.

There is an issue with this approach though. The accelerometers are not only sensitive to the gravity, they are also sensitive to the acceleration (hence the name). If your subject moves, its acceleration will cause an error in the estimate of the gravity vector. The estimate is poor in the short term, but it should be good in the long term: as your subject is unlikely to maintain *sustained* acceleration, a time average of the accelerometer readings should closely match the gravity vector.

### Using the gyroscopes

In order to get rid of the acceleration-induced errors, you can instead use the gyro readings. Assuming you somehow manage to get an initial estimate of the gravity vector, you can use the gyro readings to iteratively update this estimate:

```
at each time step:
    (accel, gyro) = read_MPU();
    dt = time_since_previous_time_step;
    rotation = - dt * gyro;
    gravity = apply_rotation(rotation, gravity);

```

here `rotation` is the rotation vector describing how much the gravity has rotated since the previous time step. The minus sign in its formula comes from the fact that the gyro gives you the rotation of the device relative to a still reference frame, whereas you want the rotation of a still vector relative to the device's reference frame. The function `apply_rotation()` would apply Rodrigues' rotation formula in order to rotate the gravity vector to its new orientation.

This approach does not suffer from the acceleration induced errors. It is, however prone to drift, as combining a large number of small rotations ends up piling up a large number of small errors.

### Combining gyroscope and accelerometer data

The accelerometer approach is prone to short-term errors, while the gyroscope approach is prone to long-term drift. You can try to combine these two approaches, and use the accelerometers to determine the long-term behavior of your gravity estimate, while the gyroscopes determine its short-term behavior. For this you would, at each time step:

* use the gyro data to rotate the current estimate of the gravity vector
* then “stir” it gently towards the accelerometer readings.

In pseudo-code, this would look like:

```
at each time step:
    (accel, gyro) = read_MPU();
    dt = time_since_previous_time_step;
    rotation = - dt * gyro;
    gravity = apply_rotation(rotation, gravity);
    gravity = gravity + (dt/tau) * (accel - gravity)

```

The last line has the effect of slightly pushing the gravity estimate towards the accelerometer readings. Note that this line looks like the implementation of a first-order low-pass filter with time constant `tau`. This time constant defines the boundary between the “short” time scales, where you trust the gyroscopes more than the accelerometers, and the “long” time scales, where you trust more the accelerometers. The value of `tau` has to be chosen by experiment. It controls the trade-off between the noise coming from the acceleration and the systematic error coming from the gyros.

With this formula, the accumulated gyro errors will always stay bound, with a total error proportional to `tau`. Since the step-wise rotations are presumably very small, and since the rotation errors do not pile up in an unbounded way, you can probably get away with using a linearization of the Rodrigues' rotation formula (cos θ = 1, sin θ = θ):

```
gravity = gravity + rotation × gravity

```

and then you need no trigonometry at all.

It is also worth noting that, with this approach, you can safely initialize `gravity` to zero: it will immediately start growing as the program runs, and its magnitude will eventually converge to the appropriate value.

### Getting the pitch and roll

Once you know the gravity vector, you can easily compute the pitch and roll. I am not saying that you should completely avoid using angles: you probably want angles on your user interface. What I am saying is that you should refrain from using angles for the purpose of keeping track of the device's orientation. Computing the angles as a post-processing step is fine.

Actually, you may as well compute those angles in the computer that does the final processing of the data. The ESPs can simply send their best estimate of the gravity vector, and let the computer do the trigonometry.
> 4 votes

# Answer
You have the right idea fusing data from both gyro and accelerometer. However, I would strongly advise against doing the fusion yourself since there is a dedicated Digital Motion Processor (DMP) on your MPU-6050 that does this for you. You just need a library that grabs data from the DMP. As far as I know the only Arduino libraries that do this are ones based on Jeff Rowberg's work.

The data outputted by the DMP is in quaternion format. Jeff converts it to yaw pitch and roll but his conversion is flawed (it produces spurious flips and rotations at north and south poles, called gimbal lock). Don't worry, this can be fixed.

If using Jeff's library (or one based on it) you'll need to make sure the detector is level and still before sending a character over serial to trigger the calibration and you need to do this every time you power on. The library and sketches are somewhat overwhelming/intimidating to new users. This too can be fixed.

If you want to

(a) Learn more about this whole topic

(b) Use the correct conversion from quaternion to yaw pitch roll (one that does not produce gimbal lock)

(c) Hide Jeff's library behind a simple and easy to use interface

(d) Perform the calibration only once and have those results saved to persistent memory on your arduino so that you don't have to repeat the calibration every time you power on the device.

Then I would recommend the following tutorial:

https://youtu.be/k5i-vE5rZR0
> 2 votes

---
Tags: nodemcu, mpu6050, accelerometer, gyroscope
---


title: MPU6050 Calibrating Accelerometer

text:
# Question
Title: MPU6050 Calibrating Accelerometer
I recently got an MPU6050 and I noticed the accelerometer data was a bit off, especially on the Z axis.

I'm running it on a Teensy 4.0 with Adafruit's MPU6050 library and basic example code: https://github.com/adafruit/Adafruit\_MPU6050/blob/master/examples/basic\_readings/basic\_readings.ino

While stable on a flat surface (+Z up), it's reading ~8.5 m/s^2 and when flipped over (-Z up), ~11.6 m/s^2:

```
+Z:
Acceleration X: -0.06, Y: 0.00, Z: 8.44 m/s^2
-Z:
Acceleration X: -0.01, Y: -0.07, Z: -11.57 m/s^2

```

Aligning the other axes vertically gives me:

```
+X:
Acceleration X: 10.16, Y: -0.16, Z: -0.03 m/s^2
-X:
Acceleration X: -9.27, Y: -0.10, Z: -0.18 m/s^2
+Y:
Acceleration X: 0.07, Y: 9.55, Z: -0.10 m/s^2
-Y:
Acceleration X: 0.04, Y: -9.93, Z: -0.05 m/s^2

```

The X and Y readings could be adjusted fairly close to 9.81 m/s^2 with just an offset, but it seems like the Z axis would also require some scaling.

My question, is there a standard method of calibrating it in code?

# Answer
Yes an accelerometer can be calibrated. An offset for each of the 3 accelerometers can be found such that the absolute value of the maximum and minimum values of any given accelerometer axis are equal. The maximum and minimum values can be found by rotating the accelerometer such that each axes is pointed directly toward and directly away from the earth. Once each axes is normalized each axes needs a magnitude adjustment value such that the maximum value of all axes equal one another. It may be convenient the product of the maximum of any given axes and that axes' magnitude adjustment value is 9.8 (meters per second * second).
> 2 votes

# Answer
Yes. Jeff Rowberg's library performs the calibration for you when you power on. You'll need to make sure the module is lying level and still and then send a character over serial to trigger the calibration. A version based on Jeff's library, called Electronic Cats, can be downloaded directly using the Arduino IDE.

Note that Jeff's library is a bit overwhelming/intimidating for new users. If you'd like to learn more about hiding its complexity behind a simple and easy to use interface, or about being able to save the calibration results to persistent memory so that you don't have to perform the calibration every time you power on, or just want to learn more about this topic in general, please consult the following tutorial:

https://youtu.be/k5i-vE5rZR0
> -1 votes

---
Tags: mpu6050, teensy
---


# Question
Title: MPU6050 - Why is my gyro integration incorrect?
My situation:

* I am able to communicate over i2c with my MPU6050 IMU
* I can get accelerometer and gyro data
* I can compute the sensor's orientation using my accelerometer

Issue:

* when trying to compute the sensor's orientation using my gyroscope my values seem to be totally incorrect. I am computing the orientation using a complementary filter.

This is the code I use https://paste.ubuntu.com/p/vZmbnc23gj/

This is the computed orientation, when the sensor is lying on a table: https:https://paste.ubuntu.com/p/W7DzVKR9c7/ Those measurements are totally incorrect, because when moving the senor randomly around its axis it never goes above 1.8. (even when I do an 180 degree turn)

Could somebody give me some hints or explanation on why my results are incorrect and drifting so much?

# Answer
> -1 votes
You need to perform offset calibration, otherwise you'll get large drift errors. The MPU6050 has a dedicated Digital Motion Processor (DMP) where data from the gyro and accelerometer are fused for you. I recommend grabbing the results of that fusion from the DMP. As far as I know the only libraries that do this are ones based on Jeff Rowberg's work. For a detailed guide please see:

https://youtu.be/k5i-vE5rZR0

---
Tags: i2c, mpu6050
---


title: Read & Write to EEPROM

text:
# Question
Title: Read & Write to EEPROM
I need to implement EEPROM Read & Write functionality to my project.
I've been learning how to use the EEPROM on the last few days, however I'm struggling to Read & Write Strings to EEPROM.

**Debugging the Received Data:**

* Received Data: The data received is correct.
* EEPROM Data: It seem it has data but I am receiving Garbage Characters.

After reading several answers, I seem to fail understanding the reason behind my failure.
Sure I could "Copy / Paste", probably make it work and not understand the cloned code, but I wouldn't learn anything from that.
Therefore posting another thread regarding this subject (not exactly duplicate) requesting some help and/or guidance; for the sake of understanding and solving my issue.

**Code**

```
int ADDR_USERNAME       = 2;           // Username Data Lenght Address on EEPROM.

/* Get Username from EEPROM */
String EE_ReadUsername()
{
  int dataLength  = EEPROM.read(ADDR_USERNAME);       // Get the Data Length from EEPROM Address Position.
  int dataAddress = ADDR_USERNAME + 1;                // Data Initial Address on EEPROM

  char data[dataLength];                              // Assign the Array Length

  for (int i = 0; i < dataLength; i++)                // Retrieve Data (Char by Char) by Iterating over EEPROM Address Positions.
  {
    char c = EEPROM.read(dataAddress + i);            // Add EEPROM Address Char to Array
  }

  // DEBUG START
  Serial.print("VALUE: ");
  Serial.println(String(data));
  // DEBUG END

  return String(data);                                // Return the Data.
}

/* Save Username to EEPROM */
void EE_WriteUsername(String str)
{
  byte len = str.length();                            // Get the String Length.
  int dataAddress = ADDR_USERNAME + 1;                // Set the Initial Data Address

  EEPROM.update(ADDR_USERNAME, len);                  // Store the String Length to EEPROM

  for (int i = 0; i < len; i++)                       // Iterate over each char in String.
  {
    EEPROM.update(dataAddress + i, str[i]);           // Assign each char from Received String to an Address Position in EEPROM.
  }
}

```

Thanks in advance.

# Answer
In `EE_ReadUsername()`, you wrote:

```
char c = EEPROM.read(dataAddress + i);

```

This variable (`c`) is set but never used. You may want to add that character to the `data` character array.

Also, the array has to be terminated with a NUL byte.
> 1 votes

# Answer
Giving this thread some more value while taking into consideration @Edgar Bonet's help (the accepted answer for this thread); I'm answering my own question with my full header class code (more EEPROM features) for further reference for myself and other users, who might be learning.

---

**Note(s):**

1. The regions are there for a backup reference purpose.
2. Feel free to edit and improve the answer and improve comments with advanced and knowleadgeable information.
3. Null Terminating char is NOT added to the EEPROM. The Null Terminating char '\n' or '\0' is added to the array when reading (only). This prevents writing (unnecessary) addresses to EEPROM.

---

**Code**

```
#pragma region <Includes>
#include <EEPROM.h>
#pragma endregion

#pragma region <Configuration>

#define ADDR_BRIGHTNESS   0           // LCD Brightness Data Address on EEPROM.
#define ADDR_CONTRAST     1           // LCD Contrast Data Address on EEPROM. [NOT IMPLEMENTED]
#define ADDR_USERNAME     2           // Username Data Lenght Address on EEPROM.
#define ADDR_COMPUTERNAME 14          // Computer Data Length Initial Address on EEPROM.

#pragma endregion

#pragma region <CRC>
unsigned long EEPROM_CRC(void)
{
  const unsigned long crc_table[16] =
  {
    0x00000000, 0x1db71064, 0x3b6e20c8, 0x26d930ac,
    0x76dc4190, 0x6b6b51f4, 0x4db26158, 0x5005713c,
    0xedb88320, 0xf00f9344, 0xd6d6a3e8, 0xcb61b38c,
    0x9b64c2b0, 0x86d3d2d4, 0xa00ae278, 0xbdbdf21c
  };

  unsigned long crc = ~0L;

  for (int index = 0 ; index < EEPROM.length()  ; ++index)
  {
    crc = crc_table[(crc ^ EEPROM[index]) & 0x0f] ^ (crc >> 4);
    crc = crc_table[(crc ^ (EEPROM[index] >> 4)) & 0x0f] ^ (crc >> 4);
    crc = ~crc;
  }

  return crc;
}

/* Performs a Cyclic Redundancy Check and Prints a Report on Serial Monitor */
void EE_CRC()
{
  Serial.println(" *** Performing EEPROM Cyclic Redundancy Check...");
  Serial.print(" *** EEPROM Length: ");                                // Print Length of Data to run CRC on.
  Serial.println(EEPROM.length());

  Serial.print(" *** EEPROM CRC32 Data: 0x");                          // Print the Result of Calling EEPROM_CRC()
  Serial.println(EEPROM_CRC(), HEX);
}
#pragma endregion

/* Iterate Through Each byte of the EEPROM Storage and Set all of the bytes to 0. */
void EE_ERASE()
{
  Serial.println(" *** ERASING EEPROM MEMORY...");

  for (int i = 0; i < EEPROM.length(); i++)
  { EEPROM.write(i, 0); }

  Serial.println(" *** EEPROM ERASED!");
}

#pragma region <User Name>
/* Get Username from EEPROM */
String EE_ReadUsername()
{
  int dataLength  = EEPROM.read(ADDR_USERNAME);         // Get the Data Length from EEPROM Address Position.
  int dataAddress = ADDR_USERNAME + 1;                  // Data Initial Address on EEPROM

  char data[dataLength +1];                             // Assign the Array Length (+1 to Add the Null Terminating Char).

  for (int i = 0; i < dataLength; i++)                  // Retrieve Data (Char by Char) by Iterating over EEPROM Address Positions.
  {
    data[i] = EEPROM.read(dataAddress + i);             // Add EEPROM Address Char to Array
  }

  data[dataLength] = '\0';                              // Terminate the char String (Add Null Terminating Char)

  return String(data);                                  // Return the Data.
}

/* Save Username to EEPROM */
void EE_WriteUsername(String str)
{
  byte len = str.length();                              // Get the String Length.
  int dataAddress = ADDR_USERNAME + 1;                  // Set the Initial Data Address

  EEPROM.update(ADDR_USERNAME, len);                    // Store the String Length to EEPROM

  for (int i = 0; i < len; i++)                         // Iterate over each char in String.
  {
    EEPROM.update(dataAddress + i, str[i]);             // Assign each char from Received String to an Address Position in EEPROM.
  }
}
#pragma endregion

#pragma region <Computer Name>
/* Get Computer Name from EEPROM */
String EE_ReadComputername()
{
  int dataLength  = EEPROM.read(ADDR_COMPUTERNAME);     // Get the Data Length from EEPROM Address Position.
  int dataAddress = ADDR_COMPUTERNAME + 1;              // Data Initial Address on EEPROM

  char data[dataLength +1];                             // Assign the Array Length (+1 to Add the Null Terminating Char).

  for (int i = 0; i < dataLength; i++)                  // Retrieve Data (Char by Char) by Iterating over EEPROM Address Positions.
  {
    data[i] = EEPROM.read(dataAddress + i);             // Add EEPROM Address Char to Array
  }

  data[dataLength] = '\0';                              // Terminate the char String (Add Null Terminating Char)

  return String(data);                                  // Return the Data.
}

/* Save Computer Name to EEPROM */
void EE_WriteComputername(String str)
{
  byte len = str.length();                              // Get the String Length.
  int dataAddress = ADDR_COMPUTERNAME + 1;              // Set the Initial Data Address

  EEPROM.update(ADDR_COMPUTERNAME, len);                // Store the String Length to EEPROM

  for (int i = 0 ; i < len; i++)                        // Iterate over each char in String.
  {
    EEPROM.update(dataAddress + i, str[i]);             // Assign each char from Received String to an Address Position in EEPROM.
  }
}
#pragma endregion

#pragma region <Brightness>
int EE_ReadBrightness()
{
  return EEPROM.read(ADDR_BRIGHTNESS);
}

void EE_WriteBrightness(int val)
{
  EEPROM.update(ADDR_BRIGHTNESS, val);
}
#pragma endregion

```
> 1 votes

---
Tags: arduino-ide, arduino-nano, c++, string, eeprom
---


# Question
Title: How to use ESP32 ESP32 config flag in platformio?
I build my ESP32 project from platformio and I'd like to change CONFIG\_MBEDTLS\_DYNAMIC\_FREE\_PEER\_CERT in order to reduce the RAM footprint. I don't get how to do that: should I modify my platformio.ini?

# Answer
> 0 votes
Simply put, you have to update your platformio.ini as assumed in the question as follows (see last line):

```
[env:esp32dev]
platform = espressif32
board = esp32dev
framework = arduino
monitor_speed = 115200
lib_deps =
    adafruit/Adafruit NeoPixel@^1.10.0
    plerup/EspSoftwareSerial@^6.13.2
    miwagner/ESP32CAN@^0.0.1
    nilsminor/TMP117-Arduino@^1.0.2
    lbernstone/Tone32@^1.0.0
board_build.partitions = no_ota.csv
build_flags = -DCONFIG_MBEDTLS_DYNAMIC_BUFFER

```

---
Tags: esp32, platformio
---


# Question
Title: Sending analog sensor data to laptop at 1kHz via USB
I am reading analog sensor data using Arduino nano, and the required sampling rate is around 1kHz. I am using the AnalogReadSerial example provided by Arduino with a delay of 1ms, so I am expecting to get around 1000 samples per second or slightly less due to the ADC conversion delay. However, the maximum number of samples I am able to get in my laptop a little bit less than 200 samples per seconds. I have tried increasing the baud rate to 115200 but that was not helpful. Am I missing something here, or is there something I need to do to get my data at the required sampling rate?

Below is AnalogReadSerial code I used for reference:

```
// the setup routine runs once when you press reset:
void setup() {
  // initialize serial communication at 9600 bits per second:
  Serial.begin(115200);
}

// the loop routine runs over and over again forever:
void loop() {
  // read the input on analog pin 0:
  int sensorValue = analogRead(A0);
  // print out the value you read:
  Serial.println(sensorValue);
  delay(1);        // delay in between reads for stability
}

```

# Answer
> 2 votes
As I said in a comment, your code on my Uno gives me 791.5 samples/s. This is about 1263 µs per sample:

* about 110 µs for `analogRead()`, including 104 µs for the conversion proper
* presumably 1000 µs for `delay(1)`
* 153 µs for the rest of the code, mostly formatting `sensorValue` in ASCII

According to these timings, if it were not for the call to `delay()`, the Arduino should be able to complete the loop in one millisecond, and still have 737 µs to spare. The simplest way to achieve this is to follow the Blink Without Delay strategy:

```
void loop() {
    static uint32_t last_conversion_time = micros();
    if (micros() - last_conversion_time >= 1000) {
        last_conversion_time += 1000;
        Serial.println(analogRead(A0));
    }
}

```

This does give me 1000 samples per second. Note that `last_conversion_time` is updated by adding 1000 µs rather than setting it to `micros()`, so this is actually a variation on the Blink Without Delay strategy. Updating `last_conversion_time` in this fashion ensures that whenever the program gets late and misses the exact microsecond it wanted, the small timing errors do not accumulate.

For the maximum possible timing accuracy, it would be more appropriate to trigger the ADC by a timer, but that approach is more complex and requires carefully reading the datasheet of the microcontroller.

---
Tags: serial, arduino-nano, analog-sampling
---


# Question
Title: Why is the value of this uint32_t always 0?
Setting up a method to calculate ID3 frame sizes, but the variable *frsz* always returns 0. I need to pass this variable back to another method so the program can loop through the ID3 frames.

```
void frameInfo(File track, char frame[4], uint32_t ltwo[4], int32_t frsz) {
 uint8_t buff[4];
 track.seek(10);
 track.read((uint8_t *)frame, 4);

 track.seek(14);
 track.read((uint8_t *)buff,4);
 ltwo[0] = buff[0];
 ltwo[1] = buff[1];
 ltwo[2] = buff[2];
 ltwo[3] = buff[3];

 ltwo[0] = ltwo[0] * 2097152;
 ltwo[1] = ltwo[1] * 16384;
 ltwo[2] = ltwo[2] * 128;

 frsz = ltwo[0] + ltwo[1] + ltwo[2] + ltwo[3];

 track.rewind();
}

```

Am I missing some sort of initialization for this uint32?

# Answer
```
void frameInfo(File track, char frame[4], uint32_t ltwo[4], int32_t frsz) {

```

The way you did it, frsz is passed by value (ie. a copy is made, and you have changed the copy, not the original). To make it change outside the function you need to pass it by reference:

```
void frameInfo(File track, char frame[4], uint32_t ltwo[4], int32_t &frsz) {

```

Note the ampersand.
> 3 votes

---
Tags: c++
---


# Question
Title: SparkFun RedBoard PTH Kit wrongly configured hardware
I have a SparkFun RedBoard PTH Kit. It's not made by SparkFun, but by https://inmotion.pt (that doesn't exist anymore). I soldered it, and bought a FTDI adapter, but when I try to upload the blink example the Arduino IDE I get this error:

```
Sketch uses 1030 bytes (3%) of program storage space. Maximum is 32256 bytes.
Global variables use 9 bytes (0%) of dynamic memory, leaving 2039 bytes for local variables. Maximum is 2048 bytes.
avrdude: stk500_recv(): programmer is not responding
avrdude: stk500_getsync() attempt 1 of 10: not in sync: resp=0xa6
avrdude: stk500_recv(): programmer is not responding
avrdude: stk500_getsync() attempt 2 of 10: not in sync: resp=0xa6
avrdude: stk500_recv(): programmer is not responding
avrdude: stk500_getsync() attempt 3 of 10: not in sync: resp=0xa6
avrdude: stk500_recv(): programmer is not responding
avrdude: stk500_getsync() attempt 4 of 10: not in sync: resp=0xa6
avrdude: stk500_recv(): programmer is not responding
avrdude: stk500_getsync() attempt 5 of 10: not in sync: resp=0xa6
avrdude: stk500_recv(): programmer is not responding
avrdude: stk500_getsync() attempt 6 of 10: not in sync: resp=0xa6
avrdude: stk500_recv(): programmer is not responding
avrdude: stk500_getsync() attempt 7 of 10: not in sync: resp=0xa6
avrdude: stk500_recv(): programmer is not responding
avrdude: stk500_getsync() attempt 8 of 10: not in sync: resp=0xa6
avrdude: stk500_recv(): programmer is not responding
avrdude: stk500_getsync() attempt 9 of 10: not in sync: resp=0xa6
avrdude: stk500_recv(): programmer is not responding
avrdude: stk500_getsync() attempt 10 of 10: not in sync: resp=0xa6
Problem uploading to board.  See https://support.arduino.cc/hc/en-us/sections/360003198300 for suggestions.

```

Or if I try to reset while uploading:

```
avrdude: stk500_recv(): programmer is not responding
avrdude: stk500_getsync() attempt 1 of 10: not in sync: resp=0x63
avrdude: stk500_getsync() attempt 2 of 10: not in sync: resp=0xff
avrdude: stk500_getsync() attempt 3 of 10: not in sync: resp=0xfe
avrdude: stk500_getsync() attempt 4 of 10: not in sync: resp=0xff
avrdude: stk500_getsync() attempt 5 of 10: not in sync: resp=0xfe
avrdude: stk500_getsync() attempt 6 of 10: not in sync: resp=0xff
avrdude: stk500_getsync() attempt 7 of 10: not in sync: resp=0xff
avrdude: stk500_getsync() attempt 8 of 10: not in sync: resp=0xfe
avrdude: stk500_getsync() attempt 9 of 10: not in sync: resp=0xfe
avrdude: stk500_getsync() attempt 10 of 10: not in sync: resp=0xff
Problem uploading to board.  See https://support.arduino.cc/hc/en-us/sections/360003198300 for suggestions.

```

And the link here at the end suggests the problem is wrongly configured hardware: https://support.arduino.cc/hc/en-us/articles/4401874331410--Error-avrdude-when-uploading

So think the problem is that when I connect the ports from the Arduino to the FTDI, two ports don't match:

simulate this circuit – Schematic created using CircuitLab

---

Here's a picture of the soldering, though I don't think that is the problem: https://i.stack.imgur.com/aa2j5.jpg

---

I am using these drivers: https://github.com/MCUdude/MiniCore for the Arduino. With these settings:

The options only have these variants:

* 328P / 328PA
* 328 / 328A
* 328PB

But my processor says 328P-PU. I tried every one of them and they all give me the same error above.

---

Can I even use this FTDI adapter? If yes what would the setup be?

# Answer
I got it to work!

The problem was that I had connected the Arduino to the FTDI and not both the FTDI and the Power Brick. The SparkFun product page said that you can use like that, and the version from https://inmotion.pt that I have is identical so I though it should have worked.

Thank's a lot @jurah for you help!
> 0 votes

---
Tags: arduino-ide, atmega328, ftdi, port-mapping
---


title: Matrix Keyboard

text:
# Question
Title: Matrix Keyboard
I'm trying to program a mechanical keyboard running on the Arduino Pro Micro (5V/16MHz). I'm using a matrix approach (4x12), and while I believe the code and the wiring (both of which I've checked multiple times) are correct, I can't get the first two rows to work no matter what. I've tried wiring it up to other pins, which works, but only for two rows at a time, when I hook up all the 4 rows, the two ones on top don't work. The code:

```
/*cols and rows*/
byte rows[] = {2,3,4,5};
const int row_Count = 4;
byte cols[] = {6,7,8,9,10,14,15,16,18,19,20,21};
const int col_Count = 12;

byte keyboard[col_Count][row_Count];

void read_layout() {
    /*do the columns*/
    for (int col_Index=0; col_Index < col_Count; col_Index++) {
        /*setup for registering the column state*/
        byte cur_Col = cols[col_Index];
        pinMode(cur_Col, OUTPUT);
        digitalWrite(cur_Col, LOW);

        /*do the rows*/
        for (int row_Index=0; row_Index < row_Count; row_Index++) {
            byte row_Col = rows[row_Index];
            pinMode(row_Col, INPUT_PULLUP);
            keyboard[col_Index][row_Index] = digitalRead(row_Col);
            pinMode(row_Col, INPUT);
        }
        /*disable the column*/
        pinMode(cur_Col, INPUT);
    }
}

void print_layout() {
    for (int row_Index=0; row_Index < row_Count; row_Index++) {
        Serial.print(row_Index);
        Serial.print(F(": "));

        for (int col_Index=0; col_Index < col_Count; col_Index++) {
            Serial.print(keyboard[col_Index][row_Index]);
            if (col_Index < col_Count) Serial.print(F(", "));
        }
        Serial.println("");
    }
    Serial.println("");
}

void setup() {
    Serial.begin(115200);
    delay(2000);
    /*init the rows*/
    for(int i=0; i<row_Count; i++) {
        pinMode(rows[i], INPUT);
    }
    /*init the cols*/
    for (int i=0; i<col_Count; i++) {
        pinMode(cols[i], INPUT_PULLUP);
    }
}

void loop() {
    read_layout();
    print_layout();

}

```

This is the schematic, a "dirty sketch":

# Answer
> 1 votes
You are using the diodes in series, which leads to accumulating forward voltages in the lower rows of your schematic. Because of this accumulation the threshold for "low" will not be crossed, and the input pin cannot recognize a pressed key.

Instead, you should adopt this circuit (copied from "Keyboard Matrix Help" by Dave Dribin). Of course, you will put the cathods on your columns pins, and the anodes on the keys.

So the right circuit uses each diode-and-key combination in parallel, not in series.

---
Tags: arduino-pro-micro, keyboard
---


title: using RTC for storage

text:
# Question
Title: using RTC for storage
I keep seeing stuff about this: https://www.arduino.cc/reference/en/libraries/rtcvars/ when looking for storage for a few variables that survive turning off and on, but then it is only on ESP8266.

The thing I am trying to understand is what it has to do with the RTC.. Other RTCs don't seem to have this arbitrary storage ability. Is the RTC in an ESP8266 nothing like any other RTC? Or is this really just some other storage on the chip? And what is the storage technology itself? If I am using an arduino uno, or just at avr chip, is there any unit I can attach that is or isn't part of an RTC with the same storage properties? Or does every RTC have this ability, and just need somebody to write the library?

According to this https://forum.arduino.cc/t/save-data-in-nonvolatile-memory/140801/2, the RTC memory of the the ESP8266 can be written to an infinite number of times, whereas an SD card will wear out if you update a value on it every second (like for a counter).

What technology is this "RTC memory" using that I can attach to my avr project?

# Answer
> 3 votes
Some RTC chips contain a small amount of battery-backed SRAM ("NVRAM" - Non-Volatile RAM) which you can use for whatever you like. This is just ordinary RAM which is powered by the small battery that keeps the RTC running.

Not all do, though, so check the specs for your chosen RTC chip.

For example, the DS1302 has:

> 31 x 8 Battery-Backed General-Purpose RAM

That's 31 bytes of storage you can use for what you like.

Conversely the DS3231 doesn't have any spare RAM at all.

---
Tags: arduino-uno, esp8266, rtc
---


# Question
Title: Problems connecting to WiFi101 access point
I currently have two Arduino Zero boards (using the SAMD21 microcontroller), each with an ATWINC1500 wifi module attached. I have established one of these units as a wifi access point with a server running on it, while the other unit is a client that attempts to connect to the access point and then send some data to the server.

As far as I can tell, the access point and the server on the first unit are created correctly. I am able to use telnet on a separate Android device to connect to the access point and send data to the server. Unfortunately, when I attempt to connect to the AP/server using the other Arduino board, it is never successful.

**Here is the code I am using on the first board to create the access point and server:**

```
WiFiServer server(23);
WiFiClient client;

void LaunchAccessPoint ()
{
    uint8_t begin_ap_status = WiFi.beginAP(access_point_name);
    if (begin_ap_status == WL_AP_LISTENING)
    {
        server.begin();
    }
}

void HandleClientConnection ()
{
    String result;
    client = server.available();
    if (client && client.connected() && client.available())
    {
        while (client.available())
        {
            result += (char) client.read();
        }

        client.stop();
    }

    SerialUSB.println(result);
}

void setup()
{
    /* ... some code in this function has been cut for clarity ... */
    LaunchAccessPoint();
}

void loop()
{
    /* ... some code in this function has been cut for clarity ... */
    HandleClientConnection();
}

```

**Meanwhile, here is the code for the client that attempts to connect to the AP/server:**

```
bool ConnectToWifi ()
{
    uint8_t wifi_connection_result = 0;
    wifi_connection_result = WiFi.begin(wifi_ssid);
    return (wifi_connection_result == WL_CONNECTED)
}

void PublishData (const char *json_string)
{
    WiFiClient client = WiFiClient();
    int client_connect_success = client.connect(IPAddress(192, 168, 1, 1), 23);
    if (client_connect_success)
    {
        int client_bytes_written = client.println(json_string);
        client.stop();
    }
}

void setup ()
{
    /* some code cut for clarity */
    ConnectToWifi();
}

void loop()
{
    /* some code cut for clarity */
    PublishData(some_string);
}

```

As I said before, *if I try using telnet on a computer or phone, it is able to successfully connect to the server and send data*. But when I attempt to use my Arduino board to act as the client, the socket gets closed by the server, as if it's actively refusing the connection.

EDIT: On the server side, the line `client = server.available();` never returns a client object if server ATWINC is AP and client is the other ATWINC.

Any suggestions? Is there something I am missing or doing wrong? Thanks!

\[edit\]

After doing some testing, it seems as though the server works *if it is not also acting as an access point*. This is unfortunate, because I need it to act as the access point *and* a server.

If anyone has experience getting two ATWINC1500s to talk to each other, where one is both an AP and a server, and the other is a client, any help would be appreciated!

\[/edit\]

# Answer
> 1 votes
The bug seems to be that the server must be started *after* the wifi has moved into the WL\_AP\_CONNECTED state. I am not sure **why** this is, but apparently sockets are invalid (or become invalidated) when the wifi access point is not in this state (or moved out of this state).

So basically, I wrote a couple small functions to handle the state of the server, and then incorporated them in my main loop like so:

```
bool is_server_launched = false;

void LaunchServer_IfDeviceConnected ()
{
    if (!is_server_launched)
    {
        uint8_t wifi_status = WiFi.status();
        if (wifi_status == WL_AP_CONNECTED)
        {
            server.begin();
            is_server_launched = true;
        }
    }
}

void StopServer_IfDeviceDisconnected ()
{
    if (is_server_launched)
    {
        uint8_t wifi_status = WiFi.status();
        if (wifi_status != WL_AP_CONNECTED)
        {
            is_server_launched = false;
        }
    }
}

void loop()
{
    LaunchServer_IfDeviceConnected();
    StopServer_IfDeviceDisconnected();
    HandleClientConnection();
}

```

I know I could have written those functions differently to be in one single function, but I'll do that at another time.

The core of this answer comes from reading the following discussion on the Arduino forums: https://forum.arduino.cc/t/mkr1000-server-in-ap-mode-socket-connection-problem/465719

In that thread, the OP had a similar issue as me. One of the people responding gave the following reply:

> Once the AP connection is lost, the server socket is no longer valid.

That person then suggested adding the following code to the OP's sketch:

```
if (status == WL_AP_CONNECTED) {
  Serial.println("Device connected to AP");
  server.begin(); // <- NEW LINE
} else {

```

After implementing that idea in my code (as I displayed above), it began to work properly.

EDIT: After doing some more digging, I also found this related issue posted in the WiFi101 Github repository:

https://github.com/arduino-libraries/WiFi101/issues/46

---
Tags: wifi, web-server, arduino-zero, samd21g
---


title: Arduino u8glib Problem

text:
# Question
Title: Arduino u8glib Problem
I am Trying to make tetris on a 128x64 oled 1.3", and I am using the u8glib library. Here Is My Code:

```
#include "U8glib.h"

U8GLIB_SH1106_128X64 u8g(13, 11, 10, 9);

int val = -53;
int val2 = -53;

void setup() {
  // put your setup code here, to run once:
  Serial.begin(9600);
 // u8g.firstPage();
  //draw();
}

static const uint8_t PROGMEM tetris1 [] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
};

static const uint8_t PROGMEM tetris2 [] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
};

void draw() {
  u8g.drawBitmapP(val, 41, 16, 64, tetris1);
}

void d() {

}
void draw2() {
 u8g.firstPage();
 do {
  u8g.drawBitmapP(val2, 41, 16, 64, tetris2);
  val2 += 1;
  delay(250);
 }while(u8g.nextPage());
}

void loop() {
  // put your main code here, to run repeatedly:
  u8g.firstPage();
  do {
    draw();
  }while (u8g.nextPage());
  draw2();
}

```

The Problem is that when I call draw2() it creates a new page only displaying the shape from function draw2(), but what I want is for the shape from function draw() to stay there. Is there anyway I can do this??

# Answer
Most monochrome LCDs and operate on a principle of "pages". A page in this context is not a whole screen, but one strip of pixels, often 8 pixels high.

U8G draws the screen using these strips. It iterates over the whole screen on a page-by-page basis (a strip at a time, that is) and draws the content. Any drawing functions within that iterative loop (between `u8g.firstPage()` and the last `u8g.nextPage()`) get called for each strip and only the portion that is within the strip being drawn will be rendered.

This of course overwrites everything else on the screen. To display something it has to be within this loop of drawing each page. If you draw something in one loop then draw something else in another loop the second loop will overwrite what was there already.

This also means that you should not do anything other than drawing in a page loop. No delays, no complex calculations, etc. You want that loop to operate as fast as possible. Do any calculations outside the loop then run the loop. This is why the loop is often separated out into its own "draw" function, so you do all your work, then "draw" it to the screen.

So to draw two tetris pieces both those pieces have to be rendered within the same `.firstPage()` ... `.nextPage()` loop.
> 1 votes

---
Tags: arduino-mega, oled
---


title: Purpose of LED indicator

text:
# Question
Title: Purpose of LED indicator
I am using an arduino mega clone called the Funduino.

I am developing a python based, tkinter application that will receive the serial data that arduino sends.

However, i am witnessing some behavior that i cannot explain and i am trying to debug. I won't say anything more, because this is an arduino forum, not a python forum.

But, in the arduino, there are some leds. One of them is power, which is constantly ON, when the arduino is powered.

There is another led that is named 'L'. When i open a serial connection this is lighted up and it stays ON.

However sometimes, when i send a string to the arduino, in order to trigger some data exchange, this button is switched off.

So what does this 'L' led is, and what it means when it is turned off?

# Answer
> 3 votes
If you do not configure the pins, they are initialized as `pinMode(xx,INPUT)` which is a floating high impedance state. Per the Arduino Uno R3 schematic, that pin is on PB5/SCK/13 which is run through the op-amp (top center in the schematic) to drive the LED. Per the Arduino Mega schematic, that pin is on PB7/OC0A/OC1C/13 which isn't run through the op amp. I left mine unconfigured on a Mega clone and measured a 1.5V on 13 and had the LED on. On an Uno clone, the light was on while unconfigured, and I measured 0.9v (but my DMM seemed to draw down the voltage).

If the pin is left floating in an unknown state, it could drive the LED into an unknown state.

You can control it's state with:

```
pinMode(LED_BUILTIN,OUTPUT);  // LED is forced off (0.01V)
digitalWrite(LED_BUILTIN,1);  // force LED on (4.97)

```

or

```
pinMode(LED_BUILTIN,INPUT_PULLUP); // On, but with the internal pullup resistor, not logic gates.  Pin 13 can be shorted to ground.

```

or set it back to the default tri-state:

```
pinMode(LED_BUILTIN,INPUT); // Tri-state, undefined.
// You could control the LED from an external signal on the pin.

```

Measure the voltage at pin 13 and see what you get.

Personally, I purpose it as a status indicator light. E.g. https://github.com/drf5n/foxyPulseInduction\_Discrimination/blob/discrimination/StatusCodeLED/StatusCodeLED.ino

Because of the tri-state/op-amp LED driver on "L", you can use the light as as a logic probe--you could leave it unconfigured and jumper it to other inputs or outputs for troubleshooting and diagnostics. If you have a project monitoring one important input, rather than putting it on a different input pin and explicitly echoing it to the LED like `digitalWrite(LED_BUILTIN,digitalRead(sensorPin));` you could hook it to pin 13 to visually see the input status and just `digitalRead(sensorPin)`.

====

Note that there are two revisions of the Arduino Mega schematic.

After testing this behavior, I noticed that the my Mega clone did not match the Arduino Mega schematic at https://www.arduino.cc/en/uploads/Main/arduino-mega2560-schematic.pdf . Tracing it out, it does use the op-amp like the Uno. (Pin 1&2 of the opamp attach to the "L" LED through the third resistor in the resistor array next to the LED.)

# Answer
> 2 votes
This buildin LED is connected to an IO pin of the microcontroller on the Mega (most commonly pin 13, but might be different depending on the board). So the meaning depends on what the code on the Mega does with it.

When the board is reset (which happens on opening of serial connection), first the bootloader will run. It gives you a short blink on the buildin LED. After the bootloader finishes, your own code is in charge. Whatever you do in your code with pin 13 will be reflected on the LED. Here the meaning depends on you.

---
Tags: serial, arduino-mega, led, serial-data
---


title: Arduino Array Scope with SPI

text:
# Question
Title: Arduino Array Scope with SPI
when I try the following code the SPI works correctly (see oscilloscope plot)

```
#include <SPI.h>

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

void loop() {
  SPI.beginTransaction(SPISettings(100000, MSBFIRST, SPI_MODE3));
  byte a[] = {0xC,0xFF,0xFF,0xFF};
  SPI.transfer(a, 4);
  SPI.endTransaction();
  delay(10);
}

```

However when I move the array declaration to the a global it doesn't work any more. (see next oscilloscope plot) Why is this?

```
#include <SPI.h>

byte a[] = {0xC,0xFF,0xFF,0xFF};

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

void loop() {
  SPI.beginTransaction(SPISettings(100000, MSBFIRST, SPI_MODE3));
  SPI.transfer(a, 4);
  SPI.endTransaction();
  delay(10);
}

```

# Answer
When you call `SPI.transfer(a, 4);`, any "received data" is stored in your byte array, `a[]`. The original data is overwritten.

If you print out the contents of the array before and after the function call to `SPI.transfer()`, you will see in the serial monitor what is happening to your array contents.

Here are 2 test sketches to illustrate the difference between the array with a global scope, VS the one with a static scope.

**Global Scope**

```
// Sketch uses 2344 bytes (7%) of program storage space.
// Global variables use 193 bytes (9%) of dynamic memory.
#include <SPI.h>

byte a[] = {0xC,0xFF,0xFF,0xFF};

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

void loop() {
  SPI.beginTransaction(SPISettings(100000, MSBFIRST, SPI_MODE3));
  for(int i = 0; i < 4; i++){
    Serial.print(a[i]);
  }
  Serial.println();
  SPI.transfer(a, 4);
  SPI.endTransaction();
  for(int i = 0; i < 4; i++){
    Serial.print(a[i]);
  }
  Serial.println('\n');
  delay(1000);
}

```

**Static Scope**

```
// Sketch uses 2410 bytes (7%) of program storage space.
// Global variables use 193 bytes (9%) of dynamic memory.
#include <SPI.h>

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

void loop() {
  SPI.beginTransaction(SPISettings(100000, MSBFIRST, SPI_MODE3));
  byte a[] = {0xC,0xFF,0xFF,0xFF};
  for(int i = 0; i < 4; i++){
    Serial.print(a[i]);
  }
  Serial.println();
  SPI.transfer(a, 4);
  SPI.endTransaction();
  for(int i = 0; i < 4; i++){
    Serial.print(a[i]);
  }
  Serial.println('\n');
  delay(1000);
}

```

The following sketch should solve the problem. Using the `const` keword before the declaration of the `b[]` array is optional.

```
// Sketch uses 2436 bytes (7%) of program storage space.
// Global variables use 197 bytes (9%) of dynamic memory.
#include <SPI.h>
const byte b[] = {0xC,0xFF,0xFF,0xFF};

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

void loop() {
  SPI.beginTransaction(SPISettings(100000, MSBFIRST, SPI_MODE3));
  byte a[] = {0xC,0xFF,0xFF,0xFF};
  for(int i = 0; i < 4; i++){
    Serial.print(a[i]);
  }
  Serial.println();
  SPI.transfer(a, 4);
  SPI.endTransaction();
  memcpy(a, b, sizeof(b));
  for(int i = 0; i < 4; i++){
    Serial.print(a[i]);
  }
  Serial.println('\n');
  delay(1000);
}

```

One last edit. The compile size can be reduced by 66 bytes thanks to the `static` keyword.

```
// Sketch uses 2370 bytes (7%) of program storage space.
// Global variables use 197 bytes (9%) of dynamic memory.
#include <SPI.h>
const byte b[] = {0xC,0xFF,0xFF,0xFF};

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

void loop() {
  SPI.beginTransaction(SPISettings(100000, MSBFIRST, SPI_MODE3));
  static byte a[] = {0xC,0xFF,0xFF,0xFF};
  for(int i = 0; i < 4; i++){
    Serial.print(a[i]);
  }
  Serial.println();
  SPI.transfer(a, 4);
  SPI.endTransaction();
  memcpy(a, b, sizeof(b));
  for(int i = 0; i < 4; i++){
    Serial.print(a[i]);
  }
  Serial.println('\n');
  delay(1000);
}

```

For more information, see: Arduino.cc
> 5 votes

---
Tags: arduino-mega, spi
---


title: Can this display's address be changed?

text:
# Question
Title: Can this display's address be changed?
I need two displays hooked up to an Arduino MKR Wifi 1010, and I saw this video which shows how to do it: this video. I also would like to have a full color oled display about 1 inch big so I would like to use this display. But I don't believe that you can change the address and would not like to buy it until I find out if you can.

Thanks in advance.

# Answer
> 3 votes
There are two different OLED screens in the links you shared.

##### 1. OLED Display on Adafruit Link

The OLED display on the Adafruit link does not have an address as it communicates via the SPI interface.

##### 2. OLED Display on YouTube Link

This OLED display communicates via I2C interface. OLED displays that communicate over the I2C interface have a slave address. This provides the possibility to connect devices with different slave addresses on the same I2C line. The address of this screen can only take two different values. If you solder the 0 Ω resistor to the left field, its address will be `0x7A`; if you solder the 0 Ω resistor to the right field, its address will be `0x78`.

---

##### Suggestions

This OLED display with 0.96" screen size communicates via I2C interface and its address can be changed. If a 0 Ω resistor is connected to the **A0** pad, the I2C slave address of the OLED display will be `0x3D`; otherwise the I2C slave address of the OLED display will be `0x3C`.

---
Tags: display, adafruit
---


# Question
Title: Trouble understanding min and max parameters for the Servo motor
This picture is from arduino.cc . Could someone please help me understand these parameters min and max? I was using TinkerCad taking input for the angle using a potentiometer (having mapped correctly the input from (0 to 1023) to (0 to 180) ) but i don't see any change when i vary either min or max in my code. The servo still goes to 180-deg position when input is 1023.

# Answer
In your question you're referencing the servo library. You mention mapping ranges of 0-1023 (the sampling range of your potentiometer) and 0-180 (the degrees of rotary travel of the average hobby servo).

There is an additional important concept to get familiar with as you learn about servos. That is the Pulse Width Modulated (PWM) signal that the Arduino (or any other controller) uses to communicate with the servo to set what angle of rotation it should assume. PWM is used a few different ways in electronics, but in this scenario it is being used as a servo control signal, and the pulse width (measured as a time duration) communicates the required angle to the servo. The library you're referencing helps users by translating between angles and PWM pulse lengths. But under the covers servos always (close enough for our conversation anyway) receive a signal based on PWM.

Another complicating factor is that servos vary greatly. There is a loose convention that says that a pulse width of 1500 micro-seconds is centre position, 1000 micro-seconds is the minimum -90 degress (or 0 degrees depending on how you look at it), and 2000 micro-seconds is the maximum +90 (or 180) degrees. These match the defaults that @Bra1n notes in their answer.  (Diagram by Wikimedia user Hforesti - https://commons.wikimedia.org/wiki/File:Sinais\_controle\_servomotor.JPG, CC BY-SA 4.0, https://commons.wikimedia.org/w/index.php?curid=101951622)

But that convention is broken all the time. Some servos are capable of less than or greater than 180 degrees. Others use different pulsewidths to specify the maximum and minimum rotations. It's for this reason that the library allows the minimum and maximum pulsewidth (expressed in micro-seconds) to be specified for the particular physical servo being attached. This allows the library to correctly map to its range of travel.

Everytime you use a new type of servo (or consider buying one for a new project) you'll need to look at its datasheet to get the important information about how that servo works.

One last thought about traps for new players, I've also seen servo libraries which express the maximum and minimum servo PWM values in the range of 0-4096. Some people also express this as a % duty cycle (mixing the language of those other purposes I mentioned PWM is also used for). Knowing that these all map back to a PWM pulse width is useful for making sense as you learn more about servos. Good luck!
> 3 votes

# Answer
It's hard coded in the servo library (well it is on the ESp8266 version I used).

```
// The following values are in us (microseconds).
// Since the defaults can be overwritten in the new attach() member function,
// they were modified from the Arduino AVR defaults to be in the safe range
// of publicly available specifications. While this implies that many 180°
// servos do not operate the full 0° to 180° sweep using these, it also prevents
// unsuspecting damage. For Arduino AVR, the same change is being discussed.
 #define DEFAULT_MIN_PULSE_WIDTH      1000 // uncalibrated default, the shortest duty cycle sent to a servo
 #define DEFAULT_MAX_PULSE_WIDTH      2000 // uncalibrated default, the longest duty cycle sent to a servo
 #define DEFAULT_NEUTRAL_PULSE_WIDTH  1500 // default duty cycle when servo is attached

```

I discovered this when a servo attached to an ESP8266 was only moving half the expected angle so I modified the library (saving it as MyServo) and used that instead. You need to be careful when doing this as you can strip the servo gears if you try to move the servo outside its capable range.
> 0 votes

---
Tags: servo, pwm
---


title: I2C communication in Arduino

text:
# Question
Title: I2C communication in Arduino
In Arduino I2C we have the following lines of code:

```
wire. beginTransmission(slave addrress)
wire.write(the byte want to send)
wire. endTransmission()

```

As we know in I2C the master must verifies the presence of the slave address and making it sure by getting an ack by the slave. Among the three function listed, who does this job? Is it wire. beginTransmission? in their website it's just mentioned it initializes communication with the slave. I want to know what happens during the execution of wire. beginTransmission from I2C perspective.

Also wire.endTransmission() releases the buffer data which was created by wire. write. So who examines the presence of the slave? The first function or the 3rd?

# Answer
All the actual I2C communication is done in `Wire.endTransmission()`. Before that nothing is done on the I2C lines.

`Wire.beginTransaction()` only initializes the libraries buffer and saves the slave address in an internal variable. `Wire.write()` puts data into the internal buffer.

`Wire.endTransmission()` can then follow the I2C protocol. It generates a start condition on the bus, sends the address byte, checks for the slaves acknowledgement on the address byte, then sends the data bytes, each followed by the slaves acknowledgement. Finally it generates a stop condition.
> 4 votes

---
Tags: i2c
---


title: Servo keeps rotating

text:
# Question
Title: Servo keeps rotating
I use a 360° servo with a program I made on an Arduino Uno.

The program was meant to control two separate servos with two potentiometers on a breadboard.

When I used 180° and 90° servos, it worked fine, but when the 180° servo was swapped with a 360° servo, it kept spinning and spinning non-stop.

Could it be the knock-off board (not Arduino brand) I'm using?

```
Servo serX;    // create servo object to control a servo for x axis
Servo serY;    // create servo y axis

int pot1 = 0;  // potentiometer pin number on board
int pot2 = 1;  // potentiometer number 2
int val;       // variable to read the value from the analog pin
int val2;      // read value from other analog pin

void setup() {
  serX.attach(9);  // attaches the servo on pin 9 to the servo object
  serY.attach(10); // attach servo to number 10 pin
}

void loop() {
  val = analogRead(pot1);           // reads the value of the potentiometer
  val = map(val, 0, 1023, 0, 180);  // scale it to use it with the servo
  serX.write(val);                  // sets the servo position

  val2 = analogRead(pot2);          // reads the value of the potentiometer
  val2 = map(val2, 0, 1023, 0, 90); // scale it to use it with the servo
  serY.write(val2);                 // sets the servo position

  delay(15);                        // waits for the servo to get there
}

```

# Answer
> 3 votes
The "360°" you refer to is probably a continuous-rotation servo.

These servos behave more like motors than like the normal RC servos; the signal you send such a servo will determine its *speed* and *direction*, **not** its position, and a pulse width of 1.5 ms (the "90° setting") will make it stop.

There's an article on the Adafruit site where you can read more about this.

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


# Question
Title: Will the pro trinket gamepad library work on an Arduino Uno?
I have an Arduino Uno and I wanted to know if the pro trinket gamepad library works on an Arduino Uno since both have same atmega328p CPU chip.

# Answer
> 4 votes
The Pro Trinket has a USB connector wired to the ATmega328P, and the Pro\_Trinket\_USB\_Gamepad library uses this connection to impersonate a USB gamepad.

The Arduino Uno also has a USB connector, but it is *not* wired to the ATmega328P. It is instead connected to an auxiliary chip (an ATmega16U2) which serves exclusively as a USB-to-serial converter. Since your sketches run on the 328P, and the 328P has no access to the USB port, you cannot use this library on the Uno.

Well, actually you may be able to use the library if add an extra USB connector, and link it to the 328P. See how it is done in the schematic of the Pro Trinket 5V. Beware of the 3.6V Zener diodes: these are needed to avoid damaging the serial port of your computer.

---
Tags: arduino-uno, atmega328
---


# Question
Title: uint8_t issues when linking libraries outside of INO file
I've been trying to start my project out split into multiple files, knowing it will grow. I was templating it off of how I've done C++ files in the past: classes in an individual .h/.cpp pair and linked into the main file. I'm using the OneBitDisplay library for my OLEDs. When I include the library in my ino file and call functions within it, all works fine. When I have it linked from one of my class header files, it gives this output:

```
In file included from C:\Users\Kyle\Documents\Arduino\libraries\OneBitDisplay-master\src/OneBitDisplay.h:4:0,
                 from C:\Users\Kyle\Projects\EOS-OSC\OLED.h:1,
                 from C:\Users\Kyle\Projects\EOS-OSC\OLED.cpp:1:
C:\Users\Kyle\Documents\Arduino\libraries\BitBang_I2C-master\src/BitBang_I2C.h:67:1: error: 'uint8_t' does not name a type
 uint8_t iSDA, iSCL; // pin numbers (0xff = disabled)
 ^~~~~~~
C:\Users\Kyle\Documents\Arduino\libraries\BitBang_I2C-master\src/BitBang_I2C.h:68:1: error: 'uint8_t' does not name a type
 uint8_t bWire; // use the Wire library
 ^~~~~~~
C:\Users\Kyle\Documents\Arduino\libraries\BitBang_I2C-master\src/BitBang_I2C.h:69:1: error: 'uint8_t' does not name a type
 uint8_t iSDABit, iSCLBit; // bit numbers of the ports
 ^~~~~~~
C:\Users\Kyle\Documents\Arduino\libraries\BitBang_I2C-master\src/BitBang_I2C.h:70:1: error: 'uint32_t' does not name a type; did you mean 'char32_t'?
 uint32_t iDelay;
 ^~~~~~~~
 char32_t
C:\Users\Kyle\Documents\Arduino\libraries\BitBang_I2C-master\src/BitBang_I2C.h:75:10: error: 'uint32_t' does not name a type; did you mean 'char32_t'?
 volatile uint32_t *pSDADDR, *pSDAPORT; // data direction and port register addr
          ^~~~~~~~
          char32_t
C:\Users\Kyle\Documents\Arduino\libraries\BitBang_I2C-master\src/BitBang_I2C.h:76:10: error: 'uint32_t' does not name a type; did you mean 'char32_t'?
 volatile uint32_t *pSCLDDR, *pSCLPORT;
          ^~~~~~~~
          char32_t
C:\Users\Kyle\Documents\Arduino\libraries\BitBang_I2C-master\src/BitBang_I2C.h:82:26: error: 'uint8_t' has not been declared
 int I2CRead(BBI2C *pI2C, uint8_t iAddr, uint8_t *pData, int iLen);
                          ^~~~~~~
C:\Users\Kyle\Documents\Arduino\libraries\BitBang_I2C-master\src/BitBang_I2C.h:82:41: error: 'uint8_t' has not been declared
 int I2CRead(BBI2C *pI2C, uint8_t iAddr, uint8_t *pData, int iLen);
                                         ^~~~~~~
C:\Users\Kyle\Documents\Arduino\libraries\BitBang_I2C-master\src/BitBang_I2C.h:86:34: error: 'uint8_t' has not been declared
 int I2CReadRegister(BBI2C *pI2C, uint8_t iAddr, uint8_t u8Register, uint8_t *pData, int iLen);
                                  ^~~~~~~
C:\Users\Kyle\Documents\Arduino\libraries\BitBang_I2C-master\src/BitBang_I2C.h:86:49: error: 'uint8_t' has not been declared
 int I2CReadRegister(BBI2C *pI2C, uint8_t iAddr, uint8_t u8Register, uint8_t *pData, int iLen);
                                                 ^~~~~~~
C:\Users\Kyle\Documents\Arduino\libraries\BitBang_I2C-master\src/BitBang_I2C.h:86:69: error: 'uint8_t' has not been declared
 int I2CReadRegister(BBI2C *pI2C, uint8_t iAddr, uint8_t u8Register, uint8_t *pData, int iLen);
                                                                     ^~~~~~~
C:\Users\Kyle\Documents\Arduino\libraries\BitBang_I2C-master\src/BitBang_I2C.h:92:27: error: 'uint8_t' has not been declared
 int I2CWrite(BBI2C *pI2C, uint8_t iAddr, uint8_t *pData, int iLen);
                           ^~~~~~~
C:\Users\Kyle\Documents\Arduino\libraries\BitBang_I2C-master\src/BitBang_I2C.h:92:42: error: 'uint8_t' has not been declared
 int I2CWrite(BBI2C *pI2C, uint8_t iAddr, uint8_t *pData, int iLen);
                                          ^~~~~~~
C:\Users\Kyle\Documents\Arduino\libraries\BitBang_I2C-master\src/BitBang_I2C.h:100:1: error: 'uint8_t' does not name a type
 uint8_t I2CTest(BBI2C *pI2C, uint8_t addr);
 ^~~~~~~
C:\Users\Kyle\Documents\Arduino\libraries\BitBang_I2C-master\src/BitBang_I2C.h:104:27: error: 'uint8_t' has not been declared
 void I2CScan(BBI2C *pI2C, uint8_t *pMap);
                           ^~~~~~~
C:\Users\Kyle\Documents\Arduino\libraries\BitBang_I2C-master\src/BitBang_I2C.h:110:27: error: 'uint32_t' has not been declared
 void I2CInit(BBI2C *pI2C, uint32_t iClock);
                           ^~~~~~~~
C:\Users\Kyle\Documents\Arduino\libraries\BitBang_I2C-master\src/BitBang_I2C.h:115:36: error: 'uint8_t' has not been declared
 int I2CDiscoverDevice(BBI2C *pI2C, uint8_t i);
...

```

This keeps going for quite a while where any types from the stdint library are referenced. It seems to only occur when the library is included in a header file, not when it is in the main ino sketch. I have it linked in the ino, knowing that the compiler needs all referenced libraries placed there. When I remove the include from the header, it gives errors that it can't find types for variables that I've declared (as it should, given that these types are defined in the library I'm trying to include)

Any clues? I've never posted anything on StackOverflow, because I usually can find the answer but this one has stumped me. I'm happy to provide any other code or debugging output if needed.

# Answer
The uint8\_t and the uint32\_t types reported in your compile errors are defined in the stdint.h file. In .ino the stdint.h is included with Arduino.h (which is added at ino to cpp conversion by Arduino builder).

The BitBang\_I2C.h should include Arduino.h or stdint.h, but the author forgot to add it. Then if BitBang\_I2C.h is included in .ino, the Arduino.h is included above it and the types are defined, but if you include BitBang\_I2C.h in a cpp file which doesn't include Arduino.h or stdint.h, then the stdint defines are missing.

The workaround for this bug is to add `#include <stdint.h>` at the top of your OLED.cpp file.
> 1 votes

# Answer
Arduino IDE implicitly includes some headers. Especially "arduino.h".
You need to include "stdint.h" into your header files for completeness.
> 1 votes

---
Tags: arduino-ide, c++
---


# Question
Title: Could I put an arduino in series with a battery charger?
recently in one of my projects I have wanted to make battery powered. I was wondering if I could connect the charger to the battery and the battery to the Arduino without blowing it. The battery is 12v 7.2 Ah and the charger is 12v 1 A.

(See attached)

# Answer
> 3 votes
Just for clarity: your diagram shows the Arduino, the batteries, and the charger connected in *parallel* \- which is correct for what you want to do. However, a 12v power supply (batteries, charger, or both) are at, or very close to the maximum input voltage spec the Uno. The Uno's voltage regulator has to waste - as heat - a good deal of power in reducing the voltage to 5v. And if the power supply provides any more than 12 volts, it will exceed regulator's spec.

Update:

> how much do you think it would go over?

We can't know without knowing the specs on the particular batteries and charger. A battery charger has to apply a higher voltage than the present voltage of the battery it is trying to charge, in order to drive current into the battery against its (the battery's) voltage. You need to know more about the charger and the batteries.

Update 2:

> The batteries are 12V 7.2 Ah and they are PK12V7.2 as the product name.

Those Lead/Acid cells. I didn't find a spec for the charger, but in automotive use, Lead/Acids are charged at 14.2 volts. Your Uno's regulator won't like that. I'm guessing you measured your charger's output voltage with no load.

Try measuring it with the batteries attached and at low, medium, or almost fully charged. That should give you a better idea. We can only guess without the specs but it sounds like these components would be pushing your Uno's regulator pretty hard.

If these components and the Uno part of a system that requires 12v for some other components, I'd suggest using 2 power supplies, 12v for the components that need it, and 7 volts into Vin (or 5v, if well regulated, into the 5v pin) on your Uno. The lower voltage could be supplied by a buck converter powered off of the 12v, which would fairly efficient and require only one charger.

---
Tags: arduino-nano, power, battery, voltage, electricity
---


title: 7-Segment Display w/ Potentiometer

text:
# Question
Title: 7-Segment Display w/ Potentiometer
(Backstory) So, I took an computer engineering class in high school (grade 11 level), where I learned a bit about breadboarding as well as arduinos (I would like to stress a bit). It has been 5 years, and I don't remember much; but the other day my little brother started taking the same class. He has the following assignment, which I have also endeavored to try for fun:

(Not Backstory) I need to make a potentiometer control a 7-segment display so that it displays a number (0-9) based on the potentiometers value. I hopped on to tinkercad to test stuff out before acuatally doing anything, and I came up with the following real quick:

I've tested the above model and I know it works, but the following code does not work.

```
int a = 2;
int b = 3;
int c = 4;
int d = 5;
int e = 6;
int f = 7;
int g = 8;
int potentiometer = 9;

void setup() {
  for(int pins = 2; pins <=8; pins++){
  pinMode(pins, OUTPUT);
 }
  pinMode(potentiometer, INPUT);
}

void loop() {
  int pRes;
  pRes = analogRead(potentiometer);
  if (pRes >=0 && pRes <=101){
    //0
    digitalWrite(a, LOW);
    digitalWrite(b, LOW);
    digitalWrite(c, LOW);
    digitalWrite(d, LOW);
    digitalWrite(e, LOW);
    digitalWrite(f, LOW);
    digitalWrite(g, HIGH);
    }
  else if (pRes >=102 && pRes <=203){
     //1
    digitalWrite(a, HIGH);
    digitalWrite(b, LOW);
    digitalWrite(c, LOW);
    digitalWrite(d, HIGH);
    digitalWrite(e, HIGH);
    digitalWrite(f, HIGH);
    digitalWrite(g, HIGH);
    }
  else if (pRes >=204 && pRes <=305){
     //2
    digitalWrite(a, LOW);
    digitalWrite(b, LOW);
    digitalWrite(c, HIGH);
    digitalWrite(d, LOW);
    digitalWrite(e, LOW);
    digitalWrite(f, HIGH);
    digitalWrite(g, LOW);
    }
  else if (pRes >=306 && pRes <=407){
    //3
    digitalWrite(a, LOW);
    digitalWrite(b, LOW);
    digitalWrite(c, LOW);
    digitalWrite(d, LOW);
    digitalWrite(e, HIGH);
    digitalWrite(f, HIGH);
    digitalWrite(g, LOW);
    }
  else if (pRes >=408 && pRes <=509){
    //4
    digitalWrite(a, HIGH);
    digitalWrite(b, LOW);
    digitalWrite(c, LOW);
    digitalWrite(d, HIGH);
    digitalWrite(e, HIGH);
    digitalWrite(f, LOW);
    digitalWrite(g, LOW);
  }
  else if (pRes >=510 && pRes <=611){
    //5
    digitalWrite(a, LOW);
    digitalWrite(b, HIGH);
    digitalWrite(c, LOW);
    digitalWrite(d, LOW);
    digitalWrite(e, HIGH);
    digitalWrite(f, LOW);
    digitalWrite(g, LOW);
    }
  else if (pRes >=612 && pRes <=713){
    //6
    digitalWrite(a, LOW);
    digitalWrite(b, HIGH);
    digitalWrite(c, LOW);
    digitalWrite(d, LOW);
    digitalWrite(e, LOW);
    digitalWrite(f, LOW);
    digitalWrite(g, LOW);
    }
  else if (pRes >=714 && pRes <=815){
    //7
    digitalWrite(a, LOW);
    digitalWrite(b, LOW);
    digitalWrite(c, LOW);
    digitalWrite(d, HIGH);
    digitalWrite(e, HIGH);
    digitalWrite(f, HIGH);
    digitalWrite(g, HIGH);
    }
  else if (pRes >=816 && pRes <=917){
    //8
    digitalWrite(a, LOW);
    digitalWrite(b, LOW);
    digitalWrite(c, LOW);
    digitalWrite(d, LOW);
    digitalWrite(e, LOW);
    digitalWrite(f, LOW);
    digitalWrite(g, LOW);
    }
  else if (pRes >=918 && pRes <=1023){
    //9
    digitalWrite(a, LOW);
    digitalWrite(b, LOW);
    digitalWrite(c, LOW);
    digitalWrite(d, HIGH);
    digitalWrite(e, HIGH);
    digitalWrite(f, LOW);
    digitalWrite(g, LOW);
    }
}

```

Can someone explain to me what I've done wrong (and offer corrections)?

# Answer
1. Only the pins with labels starting with “A” (A0 through A5 on the Uno) can be used as analog inputs.
2. The pin of the potentiometer that is currently not connected has to be connected to 5V.
> 1 votes

---
Tags: arduino-uno, programming, c++, 7-segment
---