text:
NodeMCU Power supply
I got a question about externally powering my NodeMCU V3. It has an onboard voltage regulator (3v3) which breaks out to 3 header pins. Now I want to power 3v3 from an external board. Can I supply 3v3 to all of those pins at the same time? (Basically connected in parallel).
Anyone has done this before or has this experience with NodeMCU V3?
I have supplied a link below:
https://www.theengineeringprojects.com/2018/10/introduction-to-nodemcu-v3.html
Thanks a lot!

Yes, you may connect all 3V pins together (red) and all GND pins together (black), like so:

In some cases, more wires will improve the circuit. E.g. when you build the Ben Eater 8-Bit CPU, you'll find that connecting power in a ring instead of a line will reduce voltage drop by about 50%.

When first reading your question, I got the impression that you wanted to solder the 3.3 V wires directly to the voltage regulator. Here's my original answer for that:
That's not a good idea: if you connect the same wire to all pins, your're creating a short, typically causing a malfunction if not worse. You may destroy your equipment (external board as well as the NodeMCU v3). Do NOT connect 3.3V to all pins of the voltage regulator.
A voltage regulator has 3 pins:

voltage in (for an unregulated voltage you can't exactly control; typically higher than the output voltage)
voltage out (for the stabilized resulting voltage you want to have)
ground

The only pin to connect the voltage to is the "voltage in" pin (VIN). And typically, a development board has a pin for that:

However, you'll find that the input voltage must be between 4.75V and 10V, so supplying 3.3V from an external board is not sufficient.
If you have regulated (stable) 3.3V already, you can connect that to a pin labelled 3V:

Also, you need to connect the grounds (GND) of both circuits together (GND of external board to GND of NodeMCU), otherwise the current will not find its way back.

I don't believe the OP wants to short the regulator, but externally apply 3V3 to the circuit

Hi! Thanks for your replies!
Like Sim Son said, I would just like to externally supply the 3V3 pins with a voltage regulator. Would it hurt if the 3, 3V3 pins are tied together to the same net? Would it give me problems?

@sanrays10: yes, that's possible. I've updated the answer and uploaded an image where I did exactly that.

Thanks a lot! Just what I needed to know!


text:
LSM303 unable to compensate tilt
I am working on a tilt compensated compass with the LSM303DLHC. I manage to calibrate the magnetic and accelero part. I managed to calculate pitch and roll. But when it comes to calculate tilt compensation for the compass something goes wrong. My values on the serial monitor just don't make sense...If I calculate compass heading from calibrated magneto values it works using the Y axis as the magnetic vector. How would I be able to change that to the X-axis?
   LSM303DLHC including accelerometer to correct for position

*/
#include <Wire.h>

const int LSM303_ADDR = 0x19;
const int LSM303_ADDR_MAG = 0x1E;

//control register addresses
const int CTRL_REG1_ADDR = 0x20;
const int CTRL_REG2_ADDR = 0x21;
const int CTRL_REG3_ADDR = 0x22;
const int CTRL_REG4_ADDR = 0x23;
const int CTRL_REG5_ADDR = 0x24;
const int CTRL_REG6_ADDR = 0x25;

const int CRA_REG_M_ADDR = 0x00;
const int CRB_REG_M_ADDR = 0x01;
const int MR_REG_M_ADDR = 0x02;

//data register addresses LSB first for accelero, MSB first for magneto
const int Accelero_First_data_addr = 0x28;
const int Magneto_First_data_addr = 0x03;
const int Temp_out_data_addr = 0x31;//MSB first 12 bits

int CTRL_REG1_A_value = 0x47; //50Hz Low Power disable, all axes enabled
int CTRL_REG2_A_value = 0x00; //
int CTRL_REG3_A_value = 0x00; //no interrupt or watermark enabled
int CTRL_REG4_A_value = 0x00; // 2G full scale, high resolution, no SPI mode selected
int CTRL_REG5_A_value = 0x00; // nothing enabled
int CTRL_REG6_A_value = 0x00; // nothing enabled

int CRA_REG_M_value = 0x14; // Temp sens enabled, 15Hz data rate output
int CRB_REG_M_value = 0x20; // 2G is data 1100 - 980 G/LSB

int MR_REG_M_value = 0x00;

int16_t MagRaw_X_axis_value, MagRaw_Y_axis_value, MagRaw_Z_axis_value;
int16_t AccRaw_X_axis_value, AccRaw_Y_axis_value, AccRaw_Z_axis_value;

float pitch, roll;
float Xm_calibrated, Ym_calibrated, Zm_calibrated;
float Xm_norm, Ym_norm, Zm_norm, Xa_norm, Ya_norm, Za_norm;
float norm_a, norm_m;

void setup() {// put your setup code here, to run once:
  Serial.begin(9600);
  Wire.begin();
  setupLSM303();
  Serial.println("Setup complete..");
}

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

}

void setupLSM303() {
  Wire.beginTransmission(LSM303_ADDR);
  Wire.write(CTRL_REG1_ADDR);
  Wire.write(CTRL_REG1_A_value);
  Wire.endTransmission();
  Wire.beginTransmission(LSM303_ADDR);
  Wire.write(CTRL_REG2_ADDR);
  Wire.write(CTRL_REG2_A_value);
  Wire.endTransmission();
  Wire.beginTransmission(LSM303_ADDR);
  Wire.write(CTRL_REG3_ADDR);
  Wire.write(CTRL_REG3_A_value);
  Wire.endTransmission();
  Wire.beginTransmission(LSM303_ADDR);
  Wire.write(CTRL_REG4_ADDR);
  Wire.write(CTRL_REG4_A_value);
  Wire.endTransmission();
  Wire.beginTransmission(LSM303_ADDR);
  Wire.write(CTRL_REG5_ADDR);
  Wire.write(CTRL_REG5_A_value);
  Wire.endTransmission();
  Wire.beginTransmission(LSM303_ADDR);
  Wire.write(CTRL_REG6_ADDR);
  Wire.write(CTRL_REG6_A_value);
  Wire.endTransmission();
  //magneto register setup
  Wire.beginTransmission(LSM303_ADDR_MAG);
  Wire.write(CRA_REG_M_ADDR);
  Wire.write(CRA_REG_M_value);
  Wire.endTransmission();
  Wire.beginTransmission(LSM303_ADDR_MAG);
  Wire.write(CRB_REG_M_ADDR);
  Wire.write(CRB_REG_M_value);
  Wire.endTransmission();
  Wire.beginTransmission(LSM303_ADDR_MAG);
  Wire.write(MR_REG_M_ADDR);
  Wire.write(MR_REG_M_value);
  Wire.endTransmission();
}

void MagnetoDataRead() {
  Wire.beginTransmission(LSM303_ADDR_MAG );
  Wire.write(Magneto_First_data_addr);
  Wire.endTransmission();

  Wire.requestFrom(LSM303_ADDR_MAG , 6);
  if (Wire.available() <= 6) {
    MagRaw_X_axis_value = (Wire.read() << 8) | (Wire.read());
    MagRaw_Y_axis_value = (Wire.read() << 8) | (Wire.read());
    MagRaw_Z_axis_value = (Wire.read() << 8) | (Wire.read());

    float X_mag_cal = MagRaw_X_axis_value / 1100.0;
    float Y_mag_cal = MagRaw_Y_axis_value / 1100.0;
    float Z_mag_cal = MagRaw_Z_axis_value / 980.0;

    //input calibration factors
    float Xm_offset_corrected = MagRaw_X_axis_value - 0.041423;
    float Ym_offset_corrected = MagRaw_Y_axis_value + 0.022448;
    float Zm_offset_corrected = MagRaw_Z_axis_value + 0.078354;

    Xm_calibrated = 94.622065 * Xm_offset_corrected + 0.831029 * Ym_offset_corrected + 1.647934 * Zm_offset_corrected;
    Ym_calibrated = 0.831029 * Xm_offset_corrected + 93.462985 * Ym_offset_corrected + 3.416885 * Zm_offset_corrected;
    Zm_calibrated = 1.647934 * Xm_offset_corrected + 3.416885 * Ym_offset_corrected + 76.477691 * Zm_offset_corrected;

    //normalization formula
    norm_m = sqrt(sq(Xm_calibrated) + sq(Ym_calibrated) + sq(Zm_calibrated));
    Xm_norm = Xm_calibrated / norm_m;
    Ym_norm = Ym_calibrated / norm_m;
    Zm_norm = Zm_calibrated / norm_m;

    //float Heading = ((atan2(Ym_calibrated, Xm_calibrated)) * 180 ) / PI;
    //if (Heading < 0) {
    //  Heading = 360 + Heading;
    //}
    /*
        Serial.print(X_mag_cal, 10);
        Serial.print("\t");
        Serial.print(Y_mag_cal, 10);
        Serial.print("\t");
        Serial.print(Z_mag_cal, 10);
        Serial.println("\t");
    */

    delay(50);

  }
}

void AcceleroDataRead() {
  Wire.beginTransmission(LSM303_ADDR);
  Wire.write(Accelero_First_data_addr | 0x80);
  Wire.endTransmission();

  Wire.requestFrom(LSM303_ADDR, 6);
  if (Wire.available() <= 6) {
    AccRaw_X_axis_value = (Wire.read()) | (Wire.read() << 8);
    AccRaw_Y_axis_value = (Wire.read()) | (Wire.read() << 8);
    AccRaw_Z_axis_value = (Wire.read()) | (Wire.read() << 8);

    float X_Acc =  (AccRaw_X_axis_value >> 4);
    float Y_Acc =  (AccRaw_Y_axis_value >> 4);
    float Z_Acc =  (AccRaw_Z_axis_value >> 4);
//calibrate offset
    float X_acc_offset_corrected = X_Acc + 6.676443;
    float Y_acc_offset_corrected = Y_Acc - 6.622381;
    float Z_acc_offset_corrected = Z_Acc + 55.408804;
//calibrate
    float X_acc_calibrated = 0.977273 * X_acc_offset_corrected - 0.003458 * Y_acc_offset_corrected + 0.012639 * Z_acc_offset_corrected;
    float Y_acc_calibrated = -0.003458 * X_acc_offset_corrected + 0.979674 * Y_acc_offset_corrected - 0.001130 * Z_acc_offset_corrected;
    float Z_acc_calibrated = 0.012639 * X_acc_offset_corrected - 0.001130 * Y_acc_offset_corrected + 0.897083 * Z_acc_offset_corrected;
//normalize
    norm_a = sqrt(sq(X_acc_calibrated) + sq(Y_acc_calibrated) + sq(Z_acc_calibrated));
    Xa_norm = X_acc_calibrated / norm_a;
    Ya_norm = Y_acc_calibrated / norm_a;
    Za_norm = Z_acc_calibrated / norm_a;

//calculate pitch and roll
    pitch = asin(-Xa_norm) * 180 / PI;
    roll = (atan2(Ya_norm, Za_norm) * 180) / PI;
//calculate vectors fo tilt compensation
    float Xh = Xm_norm * cos(pitch * PI / 180) + Zm_norm * sin(pitch * PI / 180);
    float Yh = Xm_norm * sin(roll * PI / 180) * sin(pitch * PI / 180) + Ym_norm * cos(roll * PI / 180) - Zm_norm * sin(roll * PI / 180) * cos(pitch * PI / 180);
//calculate tilt compensated heading
    float Heading = ((atan2(Yh, Xh)) * 180.0 ) / PI;
    if (Heading < 0) {
      Heading = 360 + Heading;
    }

    Serial.print("Pitch \t");
    Serial.print(pitch);
    Serial.print("\t roll \t");
    Serial.print(roll);
    Serial.print("\t");
    Serial.println(Heading);

    delay(50);
  }
}

I have been stuck on this for a few days now. Any help is appreciated!

Are you developing on an STMicro evaluation kit?  If so you might be able to you STMicro MotionMC and MotionEC (warning, no source code!) libraries to implement a tilt compass.  Ug, my bad, this the the Arduino forum - of course you are not using an STMicro development kit!

Also, are you wanting to tilt your compass beyond normal?  As in more than, say, 30 degrees?  If you want to hold you compass at 90 degrees WRT the local surface of the Earth you will have to do more than just implement a tilt compass.

Hi! Thank you for commenting! I am developing on a NodeMcu with the Arduino IDE. My compass will not be tilted beyond these  kind of angles. Formulas used in my code are ectracted from the lsm303 app notes

Hmm, in another STMicro chip (lsm9ds1) one of the acc vectors is backwards WRT the mag.  I don't think that's a problem here w/the LSM303.  Could you be having problem converting to/from degrees/radians?  That can get confusing depending on where you are getting your trig function from.  Also, (just curious) are you keeping everything in Euler angles or are you using quaternions?

I have read somewhere that for the dlhc that the earths magnetic field is aligned along the y axis. Let me re-check the source though. Eventhough its just partially the problem I have.

Shouldn't be.  In section 1.2 figure 2 of the LSM303DLHC specifications shows the lms303 acc X+ & mag X+ (as well as the acc Y+ & mag Y+) in the same direction.  Note, not all STMicro chips are so aligned.  Careful not to use the wrong chip's example code!

Sorry I got it wrong indeed. It is aligned along the X-axis. I have to point the Y-axis down to earth for it to get valid readings. Which in my case means putting the PCB vertical. My formula for heading is from the application notes though...

That does not sound correct.   All the STMicro compass examples I have see have X and Y axis parallel with the surface of the earth and Z perpendicular to the surface of the earth. (Side note, don't bring permanent magnets close to the magnetometer.  I did and had to dig out an old degaussing tool to get the magnetometer working again.)

I have to go back to the beginning I guess in this case. I will plot raw sensor values one at a time to see what is going on. It all just does not make sense to me yet.

Now that I got the magnetometer and the accelerometer working it seems that if I tilt the compass my headings still fluctuate...eventhough I apply the formulas from the App note....

It seems I got it working! Thanks a lot for your help, I owe you a few beers. For anyone following and interested here is my code:
   LSM303DLHC including accelerometer to correct for position
  Vector calculation to be implemented
*/
#include <Wire.h>
#include <Math.h>

const int LSM303_ADDR = 0x19;
const int LSM303_ADDR_MAG = 0x1E;

//control register addresses
const int CTRL_REG1_ADDR = 0x20;
const int CTRL_REG2_ADDR = 0x21;
const int CTRL_REG3_ADDR = 0x22;
const int CTRL_REG4_ADDR = 0x23;
const int CTRL_REG5_ADDR = 0x24;
const int CTRL_REG6_ADDR = 0x25;

const int CRA_REG_M_ADDR = 0x00;
const int CRB_REG_M_ADDR = 0x01;
const int MR_REG_M_ADDR = 0x02;

//data register addresses LSB first for accelero, MSB first for magneto
const int Accelero_First_data_addr = 0x28;
const int Magneto_First_data_addr = 0x03;
const int Temp_out_data_addr = 0x31;//MSB first 12 bits

int CTRL_REG1_A_value = 0x47; //50Hz Low Power disable, all axes enabled
int CTRL_REG2_A_value = 0x00; //
int CTRL_REG3_A_value = 0x00; //no interrupt or watermark enabled
int CTRL_REG4_A_value = 0x00; // 2G full scale, high resolution, no SPI mode selected
int CTRL_REG5_A_value = 0x00; // nothing enabled
int CTRL_REG6_A_value = 0x00; // nothing enabled

int CRA_REG_M_value = 0x14; // Temp sens enabled, 15Hz data rate output
int CRB_REG_M_value = 0x20; // 2G is data 1100 - 980 G/LSB

int MR_REG_M_value = 0x00;

int16_t MagRaw_X_axis_value, MagRaw_Y_axis_value, MagRaw_Z_axis_value;
int16_t AccRaw_X_axis_value, AccRaw_Y_axis_value, AccRaw_Z_axis_value;

float pitch, roll;
float Xm_calibrated, Ym_calibrated, Zm_calibrated;
float Xm_norm, Ym_norm, Zm_norm, Xa_norm, Ya_norm, Za_norm;
float norm_a, norm_m;

void setup() {// put your setup code here, to run once:
  Serial.begin(9600);
  Wire.begin();
  setupLSM303();
  Serial.println("Setup complete..");
}

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

}

void setupLSM303() {
  Wire.beginTransmission(LSM303_ADDR);
  Wire.write(CTRL_REG1_ADDR);
  Wire.write(CTRL_REG1_A_value);
  Wire.endTransmission();
  Wire.beginTransmission(LSM303_ADDR);
  Wire.write(CTRL_REG2_ADDR);
  Wire.write(CTRL_REG2_A_value);
  Wire.endTransmission();
  Wire.beginTransmission(LSM303_ADDR);
  Wire.write(CTRL_REG3_ADDR);
  Wire.write(CTRL_REG3_A_value);
  Wire.endTransmission();
  Wire.beginTransmission(LSM303_ADDR);
  Wire.write(CTRL_REG4_ADDR);
  Wire.write(CTRL_REG4_A_value);
  Wire.endTransmission();
  Wire.beginTransmission(LSM303_ADDR);
  Wire.write(CTRL_REG5_ADDR);
  Wire.write(CTRL_REG5_A_value);
  Wire.endTransmission();
  Wire.beginTransmission(LSM303_ADDR);
  Wire.write(CTRL_REG6_ADDR);
  Wire.write(CTRL_REG6_A_value);
  Wire.endTransmission();
  //magneto register setup
  Wire.beginTransmission(LSM303_ADDR_MAG);
  Wire.write(CRA_REG_M_ADDR);
  Wire.write(CRA_REG_M_value);
  Wire.endTransmission();
  Wire.beginTransmission(LSM303_ADDR_MAG);
  Wire.write(CRB_REG_M_ADDR);
  Wire.write(CRB_REG_M_value);
  Wire.endTransmission();
  Wire.beginTransmission(LSM303_ADDR_MAG);
  Wire.write(MR_REG_M_ADDR);
  Wire.write(MR_REG_M_value);
  Wire.endTransmission();
}

void MagnetoDataRead() {
  Wire.beginTransmission(LSM303_ADDR_MAG );
  Wire.write(Magneto_First_data_addr);
  Wire.endTransmission();

  Wire.requestFrom(LSM303_ADDR_MAG , 6);
  if (Wire.available() <= 6) {
    MagRaw_X_axis_value = (Wire.read() << 8) | (Wire.read());
    MagRaw_Z_axis_value = (Wire.read() << 8) | (Wire.read());
    MagRaw_Y_axis_value = (Wire.read() << 8) | (Wire.read());

    float X_mag_cal = MagRaw_X_axis_value / 1100.0;
    float Y_mag_cal = MagRaw_Y_axis_value / 1100.0;
    float Z_mag_cal = MagRaw_Z_axis_value / 980.0;

    //input calibration factors
    float Xm_offset_corrected = X_mag_cal - 0.032874;
    float Ym_offset_corrected = Y_mag_cal + 0.047876;
    float Zm_offset_corrected = Z_mag_cal + 0.039649;

    Xm_calibrated = 92.387197 * Xm_offset_corrected - 0.307374 * Ym_offset_corrected + 1.151625 * Zm_offset_corrected;
    Ym_calibrated = -0.307374 * Xm_offset_corrected + 85.002110 * Ym_offset_corrected + 1.169755 * Zm_offset_corrected;
    Zm_calibrated = 1.151625 * Xm_offset_corrected + 1.169755 * Ym_offset_corrected + 80.276037 * Zm_offset_corrected;

    //normalization formula
    norm_m = sqrt(sq(Xm_calibrated) + sq(Ym_calibrated) + sq(Zm_calibrated));
    Xm_norm = Xm_calibrated / norm_m;
    Ym_norm = Ym_calibrated / norm_m;
    Zm_norm = Zm_calibrated / norm_m;

    /*
        Serial.print(X_mag_cal, 10);
        Serial.print("\t");
        Serial.print(Y_mag_cal, 10);
        Serial.print("\t");
        Serial.print(Z_mag_cal, 10);
        Serial.println("\t");
    */

    //float Heading = ((atan2(Ym_norm, Xm_norm)) * 180.0 ) / PI;
    //if (Heading < 0) {
    // Heading = 360 + Heading;
    //}
    //Serial.println(Heading);
    //delay(50);

  }
}

void AcceleroDataRead() {
  Wire.beginTransmission(LSM303_ADDR);
  Wire.write(Accelero_First_data_addr | 0x80);
  Wire.endTransmission();

  Wire.requestFrom(LSM303_ADDR, 6);
  if (Wire.available() <= 6) {
    AccRaw_X_axis_value = (Wire.read()) | (Wire.read() << 8);
    AccRaw_Y_axis_value = (Wire.read()) | (Wire.read() << 8);
    AccRaw_Z_axis_value = (Wire.read()) | (Wire.read() << 8);

    float X_Acc =  (AccRaw_X_axis_value >> 4);
    float Y_Acc =  (AccRaw_Y_axis_value >> 4);
    float Z_Acc =  (AccRaw_Z_axis_value >> 4);

    //calibrate offset
    float X_acc_offset_corrected = X_Acc + 6.676443;
    float Y_acc_offset_corrected = Y_Acc - 6.622381;
    float Z_acc_offset_corrected = Z_Acc + 55.408804;

    //calibrate
    float X_acc_calibrated = 0.977273 * X_acc_offset_corrected - 0.003458 * Y_acc_offset_corrected + 0.012639 * Z_acc_offset_corrected;
    float Y_acc_calibrated = -0.003458 * X_acc_offset_corrected + 0.979674 * Y_acc_offset_corrected - 0.001130 * Z_acc_offset_corrected;
    float Z_acc_calibrated = 0.012639 * X_acc_offset_corrected - 0.001130 * Y_acc_offset_corrected + 0.897083 * Z_acc_offset_corrected;
    //normalize
    norm_a = sqrt(sq(X_acc_calibrated) + sq(Y_acc_calibrated) + sq(Z_acc_calibrated));
    Xa_norm = X_acc_calibrated / norm_a;
    Ya_norm = Y_acc_calibrated / norm_a;
    Za_norm = Z_acc_calibrated / norm_a;

    //calculate pitch and roll
    /*
      pitch = asin(-Xa_norm) * 180 / PI;
      roll = asin(Ya_norm / cos(pitch * PI / 180)) * 180 / PI;
    */
    roll = atan2(Ya_norm, Za_norm);
    float  Gz2 = Ya_norm * sin(roll) + Za_norm * cos(roll);
    pitch = atan(-Xa_norm / Gz2);
    float By2 = Zm_norm * sin(roll) - Ym_norm * cos(roll);
    float Bz2 = Ym_norm * sin(roll) + Zm_norm * cos(roll);
    float Bx3 = Xm_norm * cos(pitch) + Bz2 * sin(pitch);
    float yaw = (atan2(By2, Bx3)*180)/PI;
    if (yaw < 0) {
      yaw = 360 + yaw;
    }

    float tilt = atan2(sqrt((sq(Xa_norm)+(sq(Ya_norm)))),Za_norm);

    //calculate vectors fo tilt compensation
    float Xh = Xm_norm * cos(pitch) + Zm_norm * sin(pitch);
    float Yh = Xm_norm * sin(roll ) * sin(pitch) + Ym_norm * cos(roll) - Zm_norm * sin(roll) * cos(pitch);

        // calculate tilt compensated heading
        float Heading = ((atan2(Yh, Xh)) * 180.0 ) / PI;
        if (Heading < 0) {
          Heading = 360 + Heading;
        }

    Serial.print("Pitch \t");
    Serial.print(pitch * 180 / PI);
    Serial.print("\t roll \t");
    Serial.print(roll * 180 / PI);
    Serial.print("\t tilt \t");
    Serial.print(tilt*180/PI);
    Serial.print("\t");
    Serial.println(Heading);
    delay(500);
  }
}

Found it...Magneto data is coming out XZY not XYZ...when I changed this it works! Sorry, RTFMA would have given me the answer straight away.

Glad to hear it.  But you posted the answer 10 hours ago and made a comment that it still does not work 8 hours ago.  Which is it?

Sorry for the confusion. The sensor data for magneto and accelero independently work. But when I have to combine the 2 for tilt compensation...it does not compensate...

Try changing the sign of your Z-normal value before using it in your Xh and Yh equations (about 15 lines before the end of your program).  If it works, I'll post an answer explaining why.

I have tried Za_norm = -Z_acc_calibrated/norm_a; but no luck. I also tried to change the sign in the Xh formula...also no luck...

Bummer. I'm also wondering about the pitch  calculation.  It is different than the STMicro paper I'm looking at. Are you using this stmicro 2010 documet? I can not even find that one on the STMicro web site.  Try this stmicro 2018 document.  It appears the Pitch calculation is different. You might want to print out your Pitch and Roll values to check.

Thanks for sending me that link! It is very helpful. Pitch and roll calculations were printed and the seemed to be correct. I will try to implement the calculations from the document, but for that I need some time. For the moment I can already tell you that those formula's also work. On to the next step!

source: Stack Exchange

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

sort: votes


text:
How to replace String objects with char arrays while still using string methods
I am running the following code on my ESP8266 (AI-Thinker ESP8266MOD).
I send an HTTP GET request and a pin is set to high for a 1/2 second.
However, after some time (sometimes 1hr, 2hrs, 12hrs, totally random), it stops responding to HTTP requests.
I think it might be because of heap fragmentation due to the String objects I'm using.
Questions:
How can I replace the request (in loop()) and s and text (in GenerateResponse()) objects with  char arrays?
After I replace the String objects with char arrays, how can I use the indexOf() method and + operator on the char arrays?
Will this approach help with heap fragmentation?
Is it possible to find out if heap fragmentation is the problem?
#include <ESP8266WiFi.h>

const char* ssid = "myWifi";
const char* wifiPassword = "y76ggS";
const char* passwordToOpenDoor = "/81"; //password should begin with a slash

const int doorPin = 5;

WiFiServer server(301); //Pick any port number you like
WiFiClient client;

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

  pinMode(doorPin, OUTPUT);
  digitalWrite(doorPin, 0);

  Serial.println();
  Serial.print("Connecting to ");
  Serial.println(ssid);

  WiFi.begin(ssid, wifiPassword);

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

  server.begin();
  Serial.println("Server started. Diagnostics info:");
  Serial.println(WiFi.localIP());
}

void loop() {
  client = server.available();
  if (!client) {
    return;
  }

  while(!client.available()){
    delay(1);
  }

  String request = client.readStringUntil('\r');
  client.flush();

  Serial.println(request);
  if (request.indexOf(passwordToOpenDoor) != -1) { //Is password correct?
    GenerateResponse("Password is correct");
    OpenDoor();
  }
  //Got a GET request and it wasn't the favicon.ico request, must have been a bad password:
  else if (request.indexOf("favicon.ico") == -1) {
    GenerateResponse("Password is incorrect.");
  }
}

void OpenDoor() {
  digitalWrite(doorPin, 1);
  delay(500);
  digitalWrite(doorPin, 0);
}

void GenerateResponse(String text) {
  Serial.println(text);
  String s = "HTTP/1.1 200 OK\r\n";
  s += "Content-Type: text/html\r\n\r\n";
  s += "<!DOCTYPE HTML>\r\n\r\n";
  s += "

" + text + "
";
  s += "\n";
  client.flush();
  client.print(s);
  delay(1);
}

Further to all the answers provided so far, when using char array, String.indexOf() can be replaced by strstr(str1, str2). It return position number when str2 match part of the str1.

For learning, read ` that have all the function for c string and array manipulation that you need when handling char array.

@hcheung on this line "else if (strstr(request, "favicon.ico") == -1) {" I get "ISO C++ forbids comparison between pointer and integer [-fpermissive]"

I had to remove the comparison with 1 and -1 in both if statements to get it to compile.

You already received good answer about some general ideas for
replacing String objects with C strings. Here I will try to add some
more tricks more specifically targeted to your actual situation.
I can see two places in your program where the use of String shines by
its convenience, and replacing it with C strings will require some
effort. The first is the use of Stream::readStringUntil(char) for
getting the first request line. Here
I see no better option (see edit below) than reading
the stream one character at a time, and putting those characters into an
array:
const size_t input_buffer_length = 256;

// Read a line of text up to the first '\r'.
// Returns a NUL-terminated string, without the final '\r',
// into a statically allocated buffer.
// Warning: this never times out.
const char *readline(Stream &input)
{
  static char buffer[input_buffer_length];
  size_t pos = 0;  // writing position within the buffer
  int c;           // current character
  while ((c = input.read()) != '\r') {
    if (c >= 0 && pos < sizeof buffer - 1) {
      buffer[pos++] = c;
    }
  }
  buffer[pos] = '\0';  // terminate the string
  return buffer;
}

You would use it like this:
const char *request = readline(client);

For more robustness, you may want to add a timeout. Note also that this
implementation is no reentrant, as it uses a static buffer. This is not
an issue for your use case.
Edit: As noted by hcheung in a comment, you do not need to implement
this readline() function, as you can use
Stream::readBytesUntil(), which handles the timeout
and is provided by the Arduino core:
char buffer[input_buffer_length];
client.readBytesUntil('\r', buffer, input_buffer_length);

The other place is the usage of String::operator+=(const char *) for
generating the response. Here I would advice you against using
strcat() or strncat(): these will require extra memory to store the
concatenated string which you probably do not need. Instead, you can
simply print() the pieces one by one:
void GenerateResponse(const char *text) {
  Serial.println(text);
  client.println("HTTP/1.1 200 OK");
  client.println("Content-Type: text/html");
  client.println();
  client.println("<!DOCTYPE HTML>");
  client.println("");
  client.print("

");
  client.print(text);
  client.println("
");
  client.flush();
  delay(1);
}

Alternatively, you can make use of the implicit concatenation of string
literals in order to reduce the number of calls to client.print():
void GenerateResponse(const char *text) {
  Serial.println(text);
  client.print(
      "HTTP/1.1 200 OK\r\n"
      "Content-Type: text/html\r\n"
      "\r\n"
      "<!DOCTYPE HTML>\r\n"
      "\r\n"
      "

"
  );
  client.print(text);
  client.print("
\r\n");
  client.flush();
  delay(1);
}

Instead of creating a customised readline() function, it probably cleaner to use client.readBytesUntil('\r', buffer, length) since both readStringUntil() and readBytesUntil() are all inherited from Stream class.

Thanks for your answer. It's been running now for over 12 hrs :) Looks like the String objects were the issue. I'll let you know if it's still working after a couple of days.

So here is code to get you started:
myMessageArray [256] = {'\0'}; // Define global array large enough and zero terminate

the + method is replaced by
strcpy (myMessageArray, "Text to Add");
// Initializes the myMessageArray starts at index 0
strcat (myMessageArray, "More text to Add");
// Appends to the myMessageArray starts at current index

converting numeric values to chars:
uint_16_t myNumberValue  = 31253;
char numBuffer [16] = {'\0'}; // Helper buffer for conversions

itoa (myNumberValue,numBuffer,10);  // converts an integer to a base 10 (decimal) char
itoa (myNumberValue,numBuffer,2);  // converts an integer to a base 2 (binary) char
itoa (myNuberValue,numBuffer,16);  // converts an integer to a base 16 (hex) char

itoa initilizes a char array so we need the helper array:
strcat (myMessageArray, numBuffer);

to convert float we use
dtostrf(floatVariable, StringLengthIncDecimalPoint, numVarsAfterDecimal, numBuffer);

to convert chars back to int use
int16_t myIntVar = atoi(numBuffer);

to convert chars back to floats use
float myFloatVar = atof(numBuffer, decimalsToShow); // using just atof(numBuffer)
gives you standard x.XX only 2 decimals

A working IndexOf for char arrays:
/*******************************************************************************/
/**
    \brief Finds the index of the given value in the array starting at the given index
    \author codebreaker007
    \param [in] targetArray the array to search through for the char
    \param [in] valueToFind the value to find
    \param [in] startIndex the index to start searching at
    \return the index of the value within the array

    \details This method returns INDEX_NOT_FOUND^(-1) for a null input array.
        A negative startIndex is treated as zero. A startIndex larger than the array
        length will return INDEX_NOT_FOUND(-1)
*/
/********************************************************************************/
int8_t indexOf(char* targetArray, char valueToFind, uint16_t startIndex = 0) {
  if (targetArray == NULL) {
    return INDEX_NOT_FOUND;
  }
  if (startIndex <= 0) {
    startIndex = 0;
  }
  for (uint16_t i = startIndex; i < strlen(targetArray); i++) {
    if (valueToFind == targetArray[i]) {
      return i;
    }
  }
  return INDEX_NOT_FOUND;
}

To compare char arrays you should look into the strcmp function and if you want to checkthe first n char tomatchyou use:
if (strncmp(myMessageArray , "POST", 4 ) == 0) {
// compares the first 4 chars if it matches = 0, see details in the arduino doku

Hope this comprehensive intro to char arrays helps you for your current and future projects. How to find out - convert to char arrays and if its runnibg stable that was it. Before that conversion you can never rule out String class as culprit.

Nice thorough answer. (Voted). I tend to use sprintf() and printf() in C, which is too heavy-weight for most Arduino boards. I am also not sure about the WiFiClient and WiFiServer classes and whether they have methods that return char arrays rather than strings.

This way is perfect to have buffer overflows. I propose to use snprintf function.

All the standard classes on ESP8366/32 use char (after learning the String heap problem in com heavy szenarios)  As snprintf and similar all use temporary char arrays - look into the sources - this delays the problem of heap fragmentation, but is not solving it @SBF where do you see buffer overflows I propose global char arrayscompiled to flash - I have esps running for 1.5 years now with heavy use of char arrays not a single reset/crash - same program with String-class crashes after 30+ mins

Re “A working IndexOf for char arrays”: or just use the good old strchr().

@Codebreaker007: I totally agree to avoid Sting class and use char buffer, however, if your buffer is too small when you strcat you have a buffer overflow. snprintf() has an argument to limit the maximum number of bytes to be used in the buffer. The generated string has a length of at most n-1, leaving space for the additional terminating null character.

@SBF: snprintf() is probably a little bit overkill for concatenating strings. A smaller overflow-safe alternative to strcat() is strncat().

Sure, but it replaces all the itoa fuzz too. With strncat() you need to calculate the remaining free bytes in the buffer.

You asked: "After I replace the String objects with char arrays, how can I use the indexOf() method and + operator on the char arrays?"
Short answer: You can't. If you want to use C strings (aka arrays of char), you'll have to use C string functions.
The String methods operate on String objects. The common wisdom is to avoid the String class entirely since it relies on heap memory, and Arduinos are far, far too memory-starved to be able to use a class like String which creates temporary objects on the heap.

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


text:
Creating a clock using Arduino
I want to make a large clock, 16 inch x 7.5 inch, which will display dd Month yyyy.
What would be the best way to do this?
Does Arduino have a built in clock, and I'd just need logic to turn on/off LEDs on a display that already has dd Month yyyy? Do such displays exist which I can connect to Arduino?

Presuming you intend to have a more or less standard clock the hardest part of project will be accurate timekeeping. This functionality is generally reffered to as RTC i.e. Real Time Clock.
This is probably best offloaded to a dedicated IC, this provides many benefits. The foremost is that small inexpensive modules can be bought that include, a reasonably accurate crystal, the timekeeping IC and a backup battery, so your clock doesn't forget the time when unplugged.
A good place to get started would be here it goes over using one such chip to get the time (and date).
From there you can apply your own creativity for the clock interface.
One possible option is making a wordclock interface but setup for dates.

If you are willing to go the “barebones” route, you can turn an
ATmega328P (the MCU at the heart of the Arduino Uno) into a very
accurate RTC by hooking a watch crystal to it's clock pins. Given proper
calibration, you can get an accuracy of a few seconds per year.
This would require some coding though, and is not as straightforward as
using an off-the-shelf RTC. C.f.
this answer for the details.

Usually displays with pre-determined shapes for numbers and/or letters are LCD or quite specific parts.
It's entirely doable to just use standard Alpha-Numeric LED displays, there's many tutorials and explanations to be found, if that's something you think you need, you can ask more directly towards that and many of us will probably be happy to explain.
The Arduino has its own little clock frequency. Most are probably powered by some manner of crystal making them quite accurate. Some may have an actual watch crystal running some kind of real-time timer/clock. These matters are device dependent and cannot be answered by me, as I never used an Arduino.
In the basis every Atmel (the controller brand Arduinos use) can be used to maintain a clock and calendar, even the Tiny10 can, given a stable enough external clock source.
On most simpler Atmels (and as such simpler Arduinos) you will have to maintain the numbers and how they translate to the displays yourself, that last part especially if you want your own design in the display. But you'll probably be able to get a reasonably accurate pulse that you can use to update the values with the right interval.
On the larger/more complex chips and/or Arduinos you might get a (near) complete calendar unit that can basically maintain itself and allow you to just read the values. But then those will be more expensive and able to do many, many much cooler things, so that might be a bit of a waste for just a clock and doing the calendar stuff yourself is very good exercise for getting to know the processors you are working with.
For more assistance you will need to be much more specific about what Arduino/Atmel you are using and exactly what manner of display you want: Are blocky number/letter like those in radio's and alarm clocks okay, or do you want something self-designed or more flowy? Are you willing to actually use a dot-type display and learn to use that (no that hard, to be honest, but very different from segment), allowing you to display anything that fits the dots? Like smiley-like graphics, Chinese characters to some extend, etc.

Most Arduinos are clocked off a ceramic resonator. Not accurate enough for for making a clock. The Leonardo and the Micro have quartz crystals though.

Unless you use a DS3231 RTC.  It can also set alarms,:  https://arduino.stackexchange.com/questions/30638/how-to-set-alarms-on-the-ds3231-easily

It is possible to use the RTC. Another option is to use the Arduino Yun. This has a OpenWRT (Linux) running alongside the Atmel and is a little bit more expensive than the cosyt of the RTC and an Arduino. However, you can query the Linux side for the time with the Arduino command:
String GetDateAndTime (void) {
  Process time;
  String junkString = "";
  time.runShellCommand("date +\"%F %T\"");
  while(time.available()) {
    char c = time.read();
    junkString += c;
  }
  junkString = junkString.substring(0,junkString.length()-1);
  return(junkString);
}

And you can update the Linux clock periodically using the code:
/**************************************************************************/
// Update Clock on the OpenWRT Side using NTP
// command kinda swiped from:
// http://karlduino.wordpress.com/2014/01/14/set-clock-on-arduino-yun/
void forceNTPUpdate()
{
  Process date;
  String junkString;
  date.runShellCommand("ntpd -qn -p 0.pool.ntp.org");
  junkString = "";
  while(date.available()) {
    char c = date.read();
    junkString += c;
  }
}

Update the clock when the code starts to set the time and update as needed  to keep things as accurate as you like.

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


text:
Changes to user included library
I've been putting a small helper library together which I'm just including manually via the libraries sub-directory. I've just made some changes to the library in the filesystem however when trying to compile a previous sketch referencing it (after making the appropriate changes), the compiler is complaining and it appears to still be using the old version of the library. What's going on here and what is the correct way to update such a library?
I have tried completely reloading the Arduino IDE to flush out any caches etc. but that didn't help

rename the library file and see if the compiler complains that it cannot find it

The file path should be included in any error message from the compiler and that should tell you if it's really using the file you think.

Whatever compiler you are using (Arduino IDE?) should have a 'verbose' setting that you can activate.  This will give you a HUGE amount of output, but will also show you exactly what file is being accessed for the library in question.
When I do this, I copy/paste the entire output into Notepad++ and use its search capabilities to sort through all the chaff.
Frank


text:
Is there something wrong with my code or my Arduino is malfunctioning
A 12v motor is connected to a 5v relay and a HC-SRO4 is connected to an Arduino. Sometimes the relay clicks so the motor is on for less than 170 seconds which is the delay time but sometimes the motor just keep on running but also there are times that it works properly so I am wondering if my Arduino or my relay is malfunctioning or there's something wrong with my code?
int echopin=10;
int trigpin=9;
int motorpin=8;
int sensorval;
int delayt=170;
int greenpin=7;
int redpin=2;

void setup() {
  Serial.begin(9600);
  pinMode(echopin,INPUT);
  pinMode(trigpin,OUTPUT);
  pinMode(motorpin,OUTPUT);
  pinMode(redpin,OUTPUT);
  pinMode(greenpin,OUTPUT);
}

void loop() {

 digitalWrite(trigpin,LOW);
 delayMicroseconds(10);
 digitalWrite(trigpin,HIGH);
 delayMicroseconds(10);
 digitalWrite(trigpin,LOW);
 delayMicroseconds(10);
 sensorval=pulseIn(echopin,HIGH);
 Serial.println(sensorval);

 if(sensorval<500){
 digitalWrite(motorpin,HIGH);
 digitalWrite(greenpin,HIGH);
 digitalWrite(redpin,LOW);
 delay(delayt);
 digitalWrite(motorpin,LOW);
 digitalWrite(greenpin,LOW);
 digitalWrite(redpin,HIGH);
 delay(1500);
 }
 digitalWrite(motorpin,LOW);
 digitalWrite(redpin,HIGH);
 digitalWrite(greenpin,LOW);

 if(sensorval>500){
 digitalWrite(greenpin,LOW);
  digitalWrite(redpin,HIGH);
  digitalWrite(motorpin,LOW);
 }

}

what is redpin and greenpin? .... why are you providing incomplete information? ... you said nothing about the values printed in serial monitor


text:
Problem with my motor and L293D motor shield module
I connected my motor and a servo to my L293D motor shield and i used a 3.7 volt battery with 4800 mAh. I also connected a button to on and off the motor for a certain amount of time but only the servo is working properly while my motor doesn't run.
HERE IS THE CODE
int LEDPin=11;
int buttonPin=4;
int buttonNew;
int buttonOld=1;
int dt=100;
#include <Servo.h>
#include <AFMotor.h>
Servo myservo;
int servopin(10);
AF_DCMotor motor1(1);

void setup(){
  Serial.begin(9600);
  pinMode(LEDPin,OUTPUT);
  pinMode(buttonPin,INPUT);
  myservo.attach(servopin);
  motor1.setSpeed(200);
}

void loop(){
  buttonNew=digitalRead(buttonPin);
  if(buttonOld==0 && buttonNew==1){
    if (LEDState==0){
      digitalWrite(LEDPin,HIGH);
      myservo.write(0);
      Serial.print(buttonOld);
     int motorpos='0';
     int motorpos2='1';
      if (motorpos=='0'){
        motor1.run(FORWARD);
        delay(2000);
        motorpos='1';
      }
      if(motorpos='1'){
        motor1.run(RELEASE);
      }
       LEDState=1;
    }
    else{
      digitalWrite(LEDPin,LOW);
      myservo.write(90);
      Serial.print(buttonNew);
      int motorpos='0';
      int motorpos2='1';
      if (motorpos=='0'){
        motor1.run(BACKWARD);
        delay(2000);
        motorpos='1';
      }
      if (motorpos='1'){
        motor1.run(RELEASE);
      }
        LEDState=0;
    }
  }
  buttonOld=buttonNew;
  delay(dt);
}

what seems to be the problem because my motor doesn't work with this code but with a different code it works

just to be sure that the motor isn't broken or the problem

Sorry for that @jsotola I will consider it next time, thank you!

Posting a schematic, not a frizzy thing will help. You can lose a fair amount of voltage using the L293D shield. A MOSFET bridge would be much better.


text:
How do I use a shift register with ioAbstraction?
I’m trying to combine this use of the shift register.
With the ioAbstaction library.
But I’m not sure how to read the buttons.
The help in the library seems to suggest more pins for writing than the tutorial for the buttons.
The end goal is to have three LEDs and the buttons connected through the
74HC595 shift register using a minimal number of Ardunio pins.

Downvoter. Why? Is there something constructive you add?

The 74HC595 is a SerialToParallel shift register, mainly to have multiple outputs (SIPO).
You can abuse it to read multiple buttons by multiplexing:
Have one Arduino input pin and several output pins on the shift register to select the current button. This is what the instructables.com is showing.
No idea how that ioAbstraction library might help more than the Arduino-builtin shiftOut() function...

The IoAbstraction library is to enabled event-driven programming, if that helps.

I don't know that library, but I fear you have to enhance it a lot for your needs. And if you want to control your leds with that 595 as well, you got a very specific task I don't see how a generic library might help.


text:
DHT11 is returning nonsensical values
I am trying to get humidity and temperature readings (eventually to trigger a misting system), but the values keep returning as 0C and 0%humidity (in general).  Originally, I was using an am2320 sensor and using the analog pins.  Here, I used the following code:
#include "dht.h"
#define dht_apin A2 // Analog Pin sensor is connected to
#define MIST 7
#define LIGHT 2

dht DHT;

void setup(){
 pinMode(MIST, OUTPUT);
 pinMode(LIGHT, OUTPUT);
  Serial.begin(9600);
  delay(500);//Delay to let system boot
  Serial.println("DHT11 Humidity & temperature Sensor\n\n");
  delay(1000);//Wait before accessing Sensor

}//end "setup()"

void loop(){
  //Start of Program

    DHT.read11(dht_apin);

    Serial.print("Current humidity = ");
    Serial.print(DHT.humidity);
    Serial.print("%  ");
    Serial.print("temperature = ");
    Serial.print(DHT.temperature);
    Serial.println("C  ");

    delay(5000);     //Wait 5 seconds before accessing sensor again.

  }

  //Fastest should be once every two seconds.

// end loop()
}

Thinking the sensor may have not been working, I tried using a different sensor (DHT11), and following the tutorials got the same result using this code:
#include <dht11.h>
#define DHT11PIN 4

dht11 DHT11;

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

}

void loop()
{
  Serial.println();

  int chk = DHT11.read(DHT11PIN);

  Serial.print("Humidity (%): ");
  Serial.println((float)DHT11.humidity, 2);

  Serial.print("Temperature (C): ");
  Serial.println((float)DHT11.temperature, 2);

  delay(2000);

}
// end loop()

The Arduino is being powered by a wall wart and is also connected to my computer via USB (I read that sometimes the USB doesn't supply enough power).  The weird part is that for about 1 minute I got reasonable results (humidity ~50%, temp 22C).  Then, I tried adding an if loop to turn on an LED if the humidity dropped below 60% (thinking I could use the same code to operate a relay to turn on a misting system).  The LED lit up, but the readout went back to the 0%humidity and 0C.  I have since deleted this loop but cannot seem to get reasonable measurements.  If I change the signal pin, I sometimes get a new readout 255% humidity and 255C, but I haven't been able to repeat this reliably.
For the wiring:  S to pin, + to 5V, - to GND
Note:  I have tried every analog pin and "regular" pin, so the code may designate something that is different in my picture.  When testing, I have triple checked that the signal pin in the code is correct for my wiring configuration.  I've also tried with a different Arduino with the same result.  I'm pretty new at this, but the code is pretty much copy-paste and there are only 3 wires.  I've read that there are many DHT libraries, so I'm thinking my issue has something to do with that, but I have no clue how to judge the appropriateness of a library for my application.

[[[[[[[[[[[[p

Does your DHT11 board has a pull up resistor on it? The Data pin requires a pull-up resistor (4.7k would be okay) to 5V.

Have you tried a different library, to rule out hardware issues?

You need to add the following line of code in the setup() function:
    dht.begin();

Connect the sensor as in this diagramm (including a 10k resistor!):

Watch the empty connector opposite to your breadboard plug-in
and use the following test sketch with this library:
// Example testing sketch for DHT humidity/temperature sensor

#include "DHT.h"

#define DHTPIN 4     // Digital pin connected to the DHT sensor

#define DHTTYPE DHT11   // DHT 11

// Connect pin 1 (on the left) of the sensor to +5V
// NOTE: If using a board with 3.3V logic like an Arduino Due connect pin 1 to 3.3V instead of 5V!
// Connect pin 2 of the sensor to whatever your DHTPIN is
// Connect pin 4 (on the right) of the sensor to GROUND
// Connect a 10K resistor from pin 2 (data) to pin 1 (power) of the sensor

// Initialize DHT sensor.
// Note that older versions of this library took an optional third parameter to
// tweak the timings for faster processors.  This parameter is no longer needed
// as the current DHT reading algorithm adjusts itself to work on faster procs.
DHT dht(DHTPIN, DHTTYPE);

void setup() {
  Serial.begin(9600);
  Serial.println(F("DHTxx test!"));

  dht.begin();
}

void loop() {
  // Wait a few seconds between measurements.
  delay(2000);

  // Reading temperature or humidity takes about 250 milliseconds!
  // Sensor readings may also be up to 2 seconds 'old' (its a very slow sensor)
  float h = dht.readHumidity();
  // Read temperature as Celsius (the default)
  float t = dht.readTemperature();
  // Read temperature as Fahrenheit (isFahrenheit = true)
  float f = dht.readTemperature(true);

  // Check if any reads failed and exit early (to try again).
  if (isnan(h) || isnan(t) || isnan(f)) {
    Serial.println(F("Failed to read from DHT sensor!"));
    return;
  }

  // Compute heat index in Fahrenheit (the default)
  float hif = dht.computeHeatIndex(f, h);
  // Compute heat index in Celsius (isFahreheit = false)
  float hic = dht.computeHeatIndex(t, h, false);

  Serial.print(F("Humidity: "));
  Serial.print(h);
  Serial.print(F("%  Temperature: "));
  Serial.print(t);
  Serial.print(F("°C "));
  Serial.print(f);
  Serial.print(F("°F  Heat index: "));
  Serial.print(hic);
  Serial.print(F("°C "));
  Serial.print(hif);
  Serial.println(F("°F"));
}

2 issues:  1.) The code is giving an "error compiling for board Arduino" (full error message at bottom)  2.) I ony have 3 pins to connect, not four.  Should I try a resistor on the signal pin?
DataSheet https://www.velleman.eu/downloads/29/vma311_a4v01.pdf       Full error code

In file included from LIBRARY LOCATION/DHT_sensor_library-1.3.8/DHT_U.cpp:15:0:
LIBRARY LOCATION/DHT_U.h:36:10: fatal error: Adafruit_Sensor.h: No such file or directory
#include <Adafruit_Sensor.h>
      ^~~~~~~~~~~~~~~~~~~

compilation terminated.
exit status 1
Error compiling for board Arduino Uno.

@sumbody32point5 do you see any resistor on the sensor's breakout board? If no, then add one between signal and Vcc.

You need the additiona llib installed its asking for - read the error message: Adafruit_Sensor.h: No such file or directory Add the Adafruit_Sensor lib Install it with IDE via lib manager

@Codebreaker007 Sorry that was dumb of me - got the library.  The output is now "DHTxx test!    Failed to read from DHT sensor!" There is a resistor on the breakout board, so I don't think that is the issue.  Just to be sure, I measured the resistance berween VCC and data line and got about 10Kohms.  I'm using pin 4 as in your code and tried on other pins as well. I got one reading where the output was "Read from DHT sensor," (one single line) but then it went back to "Failed to read from DHT sensor."  Is there a way to use a multimeter to verify eveything is working?

also I measured 0.13mA in the signal wire so I would think that meant that data was being sent

If your sensor is soldered onto a pcb it might be a cold solder blob or a non connecting pin on the breadboard. You could try to directly hold the signal wire to the sensor and test. If that works check the soldering or pin connections. A defect sensor is the least possible solution.

I think that might be it - I couldn't get a real reading, but I the output changed from "failed to read DHT sensor" to "DHTxx test!" but then went back to the original output.  The sensors are pretty cheap - I might get a second one, try the same configuration, and if it works try my hand at resoldering the original (I'm assuming I will probably mess it up).  I really appreciate your help and patience @codebreaker.


text:
Is there a way to both read and write on the rising edge of the SPI Clock?
Im trying to use sipo and piso shift registers simultaneously with ESP32 using SPI. However the sipo(SN74AHC) reads data on the rising edge of clock and the piso(SN74HC165) outputs data on the rising edge of the clock. Using the arduino SPI library, there is not a spi mode that can accomidate this. As a result, I am losing a bit from either device no matter what I do.
Is there something I can do to get both read and write at the rising edge or will I be forced to read and then write, changing the spi mode in between?

Have you experimented with this?  You should still be ok with Mode 1 or 2.  You output on the rising edge and sample on the falling edge.  The PISO won't change the data bit until the next rising edge, so it will still be good to read when the clock falls.


text:
nrf24L01 with/without antenna
the function write in nrf24LO1 (without antenna) works perfectly
but in nrf24LO1 (with antenna) not works. why?!
the code
#include <SPI.h>
#include <nRF24L01.h>
#include <RF24.h>
#include <printf.h>

 RF24 radio(7,8);
 const byte address[6] = "00001";
void setup() {
  radio.begin();
  radio.setDataRate(RF24_250KBPS);
  radio.openWritingPipe(address);
  radio.setPALevel(RF24_PA_HIGH);
  radio.setCRCLength(RF24_CRC_8);
  radio.stopListening();
  Serial.begin(9600);
}

void loop() {
  const char text[] = "example";
  if(radio.write(&text,sizeof(text))) //<==problem here
    Serial.println("ok");
  Serial.println(text);
  delay(1000);
}

nrf24l01 with antenna :

nrf24l01 without antenna :

In what way does it "not works"?

not works : Not send data , function write return false with 0 data sending to recever

what makes you believe that the two modules are interchangeable? .. btw, both of the modules have an antenna

They actually are interchangeable. But your program has an error radio.write expects a pointer to some data. An array and a pointer are pretty much the same in C (this is a bit oversimplified but sufficient in this case). But you are passing a pointer to an array (the address of the array), which in turn would be a pointer to a pointer to data. Your program may or may not work just because of pure luck and the current flow of aether. Remove the apmersand in that method call.

Are you communicating between identical modules? How far apart are the modules?

Try increasing the distance between the two. Or use RF24_PA_LOW during testing.


text:
Arduino Raspberry RadioHead node sends sensor data with sendtowait (ReliableDatagram) raspberry receives but node gets no ack
I have a configuration like following:
An Arduino and a raspberry both running with RadioHead library
Arduino with sensor sends data to a raspberry gateway using RHReliableDatagram with the sendtoWait method. Raspberry receives data and processes it with success. But Arduino receives no ack from raspberry. Have you any hint what the problem could be?
Arduino code
#include <RH_RF95.h>
#include <RHReliableDatagram.h>
#include <CayenneLPP.h>

///////////////////////////////////////////////////////////////////
// START CONFIGURATION
///////////////////////////////////////////////////////////////////

/* COMMENT FOR PRODUCTION USE */
#define DEBUG

// SELECT FREQUENCY APPROPRIATE TO YOUR COUNTRY
#define RF_FREQUENCY 868.0

// CHANGE HERE THE NODE ADDRESS
#define SERVER_ADDRESS 2
// GIVE EACH NODE A UNIQUE ID
#define NODE_ADDR 31

/* SELECT THE USED SENSOR TYPE */
// ONLY ONE OF THE FOLLOWING MUST BE DEFINED, IF ANY
#define ADAFRUIT_SI7021
//#define ADAFRUIT_SHT31

/* UNCOMMENT IF USING OLED DISPLAY */
//#define OLED
///////////////////////////////////////////////////////////////////
// CONFIGURATION
///////////////////////////////////////////////////////////////////

#ifdef ADAFRUIT_SI7021
#include <Adafruit_Si7021.h>
#elif defined ADAFRUIT_SHT31
#include <Adafruit_SHT31.h>
#endif

// Singleton instance of the radio driver
RH_RF95 rf95;
//RH_RF95 rf95(5, 2); // Rocket Scream Mini Ultra Pro with the RFM95W
//RH_RF95 rf95(8, 3); // Adafruit Feather M0 with RFM95

// Class to manage message delivery and receipt, using the driver declared above
RHReliableDatagram manager(rf95, NODE_ADDR);

CayenneLPP lpp(51);

#ifdef ADAFRUIT_SI7021
Adafruit_Si7021 si7021 = Adafruit_Si7021();
#elif defined ADAFRUIT_SHT31
Adafruit_SHT31 sht31 = Adafruit_SHT31();
#endif

const long InternalReferenceVoltage = 1062;  // Adjust this value to your board's specific internal BG voltage

int donePin = 4;
#ifdef ADAFRUIT_SI7021 || ADAFRUIT_SHT31
double tmp;
double hum;
#endif
double bat;
char msg[128];

// Need this on Arduino Zero with SerialUSB port (eg RocketScream Mini Ultra Pro)
//#define Serial SerialUSB

char *ftoa(char *a, double f, int precision)
{
 long p[] = {0,10,100,1000,10000,100000,1000000,10000000,100000000};

 char *ret = a;
 long heiltal = (long)f;
 itoa(heiltal, a, 10);
 while (*a != '\0') a++;
 *a++ = '.';
 long desimal = abs((long)((f - heiltal) * p[precision]));
 if (desimal < p[precision-1]) {
  *a++ = '0';
 }
 itoa(desimal, a, 10);
 return ret;
}

//read internal voltage
double readVcc() {
  long result;
  // Read 1.1V reference against AVcc
  ADMUX = _BV(REFS0) | _BV(MUX3) | _BV(MUX2) | _BV(MUX1);
  delay(2); // Wait for Vref to settle
  ADCSRA |= _BV(ADSC); // Convert
  while (bit_is_set(ADCSRA, ADSC));
  result = ADCL;
  result |= ADCH << 8;
  result = 1126400L / result; // Back-calculate AVcc in mV
  return double(result) / 1000;
}

void setup()
{
  // Rocket Scream Mini Ultra Pro with the RFM95W only:
  // Ensure serial flash is not interfering with radio communication on SPI bus
//  pinMode(4, OUTPUT);
//  digitalWrite(4, HIGH);

#ifdef DEBUG
  Serial.begin(9600);
  Serial.println("Started");
#endif

  pinMode(donePin, OUTPUT);

#ifdef ADAFRUIT_SI7021
  if (!si7021.begin()) {
#ifdef DEBUG
    Serial.println("Did not find Si7021 sensor!");
#endif
    while (true);
  }
#elif defined ADAFRUIT_SHT31
  if (!sht31.begin(0x44)) {
#ifdef DEBUG
    Serial.println("Did not find Si7021 sensor!");
#endif
    while (true);
  }
#endif

  if (!rf95.init())
#ifdef DEBUG
    Serial.println("init failed");
#endif

  // Defaults after init are 434.0MHz, 13dBm, Bw = 125 kHz, Cr = 4/5, Sf = 128chips/symbol, CRC on
  rf95.setFrequency(RF_FREQUENCY);
  rf95.setModeTx();
  rf95.setTxPower(14, false); // values between 5 to 23
  manager.setThisAddress(NODE_ADDR);
  manager.setHeaderFrom(NODE_ADDR);
}

void loop()
{

#ifdef DEBUG
  Serial.print("Sending to gateway ");
  Serial.println(SERVER_ADDRESS);
#endif

  int i = 0;
  lpp.reset();

#ifdef ADAFRUIT_SI7021
  tmp = si7021.readTemperature();
  lpp.addTemperature(1, tmp);
#ifdef DEBUG
  Serial.print("Temperature Si7021: ");
  Serial.println(tmp);
#endif
  hum = si7021.readHumidity();
  lpp.addRelativeHumidity(2, hum);
#ifdef DEBUG
  Serial.print("Humidity Si7021: ");
  Serial.println(hum);
#endif
#elif defined ADAFRUIT_SHT31
  tmp = sht31.readTemperature();
  lpp.addTemperature(1, tmp);
#ifdef DEBUG
  Serial.print("Temperature SHT31: ");
  Serial.println(tmp);
#endif
  hum = sht31.readHumidity();
  lpp.addRelativeHumidity(2, hum);
#ifdef DEBUG
  Serial.print("Humidity SHT31: ");
  Serial.println(hum);
#endif
#endif

  bat = readVcc();
  if (!isnan(bat))
  {
    lpp.addVoltage(3, bat);
#ifdef DEBUG
    Serial.print("Voltage: ");
    Serial.println(bat);
#endif
  }

#ifdef DEBUG
  Serial.print("Send data: ");
#endif

//  if (manager.sendtoWaitTimeout(lpp.getBuffer(), lpp.getSize(), SERVER_ADDRESS))
  if (manager.sendtoWait(lpp.getBuffer(), lpp.getSize(), SERVER_ADDRESS))
  {
#ifdef DEBUG
    Serial.println("OK");
#endif
  }
  else
  {
#ifdef DEBUG
    Serial.println("Failed (no reply, is server running)?");
#endif
  }

  digitalWrite(donePin, LOW);
  digitalWrite(donePin, HIGH);

#ifdef DEBUG
  delay(10000);
#endif
}

Raspberry Code:
// rf95_server.cpp
//
// Example program showing how to use RH_RF95 on Raspberry Pi
// Uses the bcm2835 library to access the GPIO pins to drive the RFM95 module
// Requires bcm2835 library to be already installed
// http://www.airspayce.com/mikem/bcm2835/
// Use the Makefile in this directory:
// cd example/raspi/rf95
// make
// sudo ./rf95_server
//
// Contributed by Charles-Henri Hallard based on sample RH_NRF24 by Mike Poublon

#include <bcm2835.h>
#include <stdio.h>
#include <signal.h>
#include <unistd.h>

#include "RadioHead/RH_RF69.h"
#include "RadioHead/RH_RF95.h"
#include "RadioHead/RHReliableDatagram.h"

#include <MQTTClient.h>
#include "SimpleIni/SimpleIni.h"

// define hardware used change to fit your need
// Uncomment the board you have, if not listed
// uncommment custom board and set wiring tin custom section

// LoRasPi board
// see https://github.com/hallard/LoRasPI
//#define BOARD_LORASPI

// iC880A and LinkLab Lora Gateway Shield (if RF module plugged into)
// see https://github.com/ch2i/iC880A-Raspberry-PI
//#define BOARD_IC880A_PLATE

// Raspberri PI Lora Gateway for multiple modules
// see https://github.com/hallard/RPI-Lora-Gateway
//#define BOARD_PI_LORA_GATEWAY

// Dragino Raspberry PI hat
// see https://github.com/dragino/Lora
#define BOARD_DRAGINO_PIHAT

// Now we include RasPi_Boards.h so this will expose defined
// constants with CS/IRQ/RESET/on board LED pins definition
#include "../RasPiBoards.h"

// Our RFM95 Configuration
#define RF_FREQUENCY  868.00
//#define RF_NODE_ID    1  replaced by gateway_id in rf95_server.ini

// Create an instance of a driver
RH_RF95 rf95(RF_CS_PIN, RF_IRQ_PIN);
//RH_RF95 rf95(RF_CS_PIN);

// Ini file
CSimpleIniA ini;

// Our MQTT Client Configuration
#define TIMEOUT 10000L
int rc;

//Flag for Ctrl-C
volatile sig_atomic_t force_exit = false;

void sig_handler(int sig)
{
  printf("\n%s Break received, exiting!\n", __BASEFILE__);
  force_exit=true;
}

int reconnect(MQTTClient client, const char* dest_addr, MQTTClient_connectOptions conn_opts)
{
  while (!MQTTClient_isConnected(client))
  {
    printf("Connect to MQTT broker on %s\n", dest_addr);
    if ((rc = MQTTClient_connect(client, &conn_opts)) == MQTTCLIENT_SUCCESS)
    {
      break;
    }
    else
    {
      fprintf(stderr, "Could not connect to MQTT broker: %d\n", rc);
      for (int i = 0; i < 10; i++)
      {
        fprintf(stderr, ".");
        delay(500);
      }
      fprintf(stderr, "\n");
    }
  }
  return 0;
}

//Main Function
int main (int argc, const char* argv[] )
{
  unsigned long led_blink = 0;

  signal(SIGINT, sig_handler);
  printf( "Starting %s\n", __BASEFILE__);

  ini.SetUnicode();
  if (ini.LoadFile("rf95_server.ini") < 0) {
    printf("Error occurred while trying to open ini file. Please provide a valid ini file\n");
    return 1;
  }
  printf("Content of rf95_server.ini\n");
  const char *project = ini.GetValue("common", "project", NULL);
  printf("project=%s\n", project);
  const char *dest_addr = ini.GetValue("common", "dest_addr", NULL);
  printf("dest_addr=%s\n", dest_addr);
  const char *client_id = ini.GetValue("common", "client_id", NULL);
  printf("client_id=%s\n\n", client_id);
  const char *gateway_id = ini.GetValue("common", "gateway_id", NULL);
  printf("gateway_id=%s\n\n", gateway_id);

  if (!bcm2835_init()) {
    fprintf( stderr, "%s bcm2835_init() Failed\n\n", __BASEFILE__ );
    return 1;
  }

  printf( "RF95 CS=GPIO%d", RF_CS_PIN);

#ifdef RF_LED_PIN
  pinMode(RF_LED_PIN, OUTPUT);
  digitalWrite(RF_LED_PIN, HIGH );
#endif

#ifdef RF_IRQ_PIN
  printf( ", IRQ=GPIO%d", RF_IRQ_PIN );
  // IRQ Pin input/pull down
  pinMode(RF_IRQ_PIN, INPUT);
  bcm2835_gpio_set_pud(RF_IRQ_PIN, BCM2835_GPIO_PUD_DOWN);
  // Now we can enable Rising edge detection
  bcm2835_gpio_ren(RF_IRQ_PIN);
#endif

#ifdef RF_RST_PIN
  printf( ", RST=GPIO%d", RF_RST_PIN );
  // Pulse a reset on module
  pinMode(RF_RST_PIN, OUTPUT);
  digitalWrite(RF_RST_PIN, LOW );
  bcm2835_delay(150);
  digitalWrite(RF_RST_PIN, HIGH );
  bcm2835_delay(100);
#endif

#ifdef RF_LED_PIN
  printf( ", LED=GPIO%d", RF_LED_PIN );
  digitalWrite(RF_LED_PIN, LOW );
#endif

  printf( " OK NodeID=%d @ %3.2fMHz\n", *gateway_id, RF_FREQUENCY );

  MQTTClient client;
  MQTTClient_connectOptions conn_opts = MQTTClient_connectOptions_initializer;
  MQTTClient_message pubmsg = MQTTClient_message_initializer;
  MQTTClient_deliveryToken token;
  char topic[128];

  printf("Create MQTT client\n");
  if ((MQTTClient_create(&client, dest_addr, client_id, MQTTCLIENT_PERSISTENCE_NONE, NULL)) != MQTTCLIENT_SUCCESS) {
    fprintf(stderr, "Creation of MQTT client failed \n");
    return 1;
  }
  conn_opts.keepAliveInterval = 20;
  conn_opts.cleansession = 1;
  reconnect(client, dest_addr, conn_opts);

  printf("Init RF95 module");
  RHReliableDatagram manager(rf95, *gateway_id);
  if (!manager.init()) {
    fprintf( stderr, "\nRF95 module init failed, Please verify wiring/module\n" );
  } else {
    // Defaults after init are 434.0MHz, 13dBm, Bw = 125 kHz, Cr = 4/5, Sf = 128chips/symbol, CRC on

    // The default transmitter power is 13dBm, using PA_BOOST.
    // If you are using RFM95/96/97/98 modules which uses the PA_BOOST transmitter pin, then
    // you can set transmitter powers from 5 to 23 dBm:
    //  driver.setTxPower(23, false);
    // If you are using Modtronix inAir4 or inAir9,or any other module which uses the
    // transmitter RFO pins and not the PA_BOOST pins
    // then you can configure the power transmitter power for -1 to 14 dBm and with useRFO true.
    // Failure to do that will result in extremely low transmit powers.
    // rf95.setTxPower(14, true);

    // RF95 Modules don't have RFO pin connected, so just use PA_BOOST
    // check your country max power useable, in EU it's +14dB
    rf95.setTxPower(14, false);

    // You can optionally require this module to wait until Channel Activity
    // Detection shows no activity on the channel before transmitting by setting
    // the CAD timeout to non-zero:
    //rf95.setCADTimeout(10000);

    // Adjust Frequency
    printf("set lora frequency to %d", RF_FREQUENCY);
    rf95.setFrequency(RF_FREQUENCY);

    // If we need to send something
    manager.setThisAddress(*gateway_id);
    manager.setHeaderFrom(*gateway_id);

    // Be sure to grab all node packet
    // we're sniffing to display, it's a demo
    rf95.setPromiscuous(true);

    // We're ready to listen for incoming message
    printf("set receive mode");
    rf95.setModeRx();

    //Begin the main body of code
    while (!force_exit) {

#ifdef RF_IRQ_PIN
      // We have a IRQ pin ,pool it instead reading
      // Modules IRQ registers from SPI in each loop

      // Rising edge fired ?
      if (bcm2835_gpio_eds(RF_IRQ_PIN)) {
        // Now clear the eds flag by setting it to 1
        bcm2835_gpio_set_eds(RF_IRQ_PIN);
        //printf("Packet Received, Rising event detect for pin GPIO%d\n", RF_IRQ_PIN);
#endif

        printf( "Listening...\n" );

        if (rf95.available()) {
#ifdef RF_LED_PIN
          led_blink = millis();
          digitalWrite(RF_LED_PIN, HIGH);
#endif
          // Should be a message for us now
          uint8_t buf[RH_RF95_MAX_MESSAGE_LEN];
          uint8_t len  = sizeof(buf);
          uint16_t from = manager.headerFrom();
          uint8_t to   = manager.headerTo();
          uint8_t id   = manager.headerId();
          uint8_t flags= manager.headerFlags();;
          int8_t rssi  = rf95.lastRssi();

          if (manager.recvfromAck(buf, &len)) {
            printf("Packet[%02d] #%d => #%d %ddB:\n", len, from, to, rssi);
            printbuffer(buf, len);
            printf("\n");

            pubmsg.payload = &buf;
            pubmsg.payloadlen = len;
            pubmsg.qos = 2;
            pubmsg.retained = 0;
            sprintf(topic, "%s/%s/%d", project, client_id, from);

            reconnect(client, dest_addr, conn_opts);
            if ((rc = MQTTClient_publishMessage(client, topic, &pubmsg, &token)) != MQTTCLIENT_SUCCESS) {
              fprintf(stderr, "Publish failed: %d\n", rc);
              force_exit = 1;
            } else {
              if ((rc = MQTTClient_waitForCompletion(client, token, TIMEOUT)) == MQTTCLIENT_SUCCESS) {
                printf("Message with token %d delivered successfully\n", token);
              }
            }
          } else {
            Serial.print("receive failed\n");
          }
        }

#ifdef RF_IRQ_PIN
      }
#endif

#ifdef RF_LED_PIN
      // Led blink timer expiration ?
      if (led_blink && millis()-led_blink>200) {
        led_blink = 0;
        digitalWrite(RF_LED_PIN, LOW);
      }
#endif
      // Let OS doing other tasks
      // For timed critical appliation you can reduce or delete
      // this delay, but this will charge CPU usage, take care and monitor
      bcm2835_delay(5);
    }
  }
  MQTTClient_disconnect(client, 10000);
  MQTTClient_destroy(&client);

#ifdef RF_LED_PIN
  digitalWrite(RF_LED_PIN, LOW );
#endif
  printf( "\n%s ending\n", __BASEFILE__ );
  bcm2835_gpio_clr_ren(RF_IRQ_PIN);
  bcm2835_close();
  return 0;
}

Thank you!
Regards
Christian


text:
How can I increase the responsiveness/speed of my stepper motor?
I'm trying to control the positioning of a NEMA17 bipolar stepper motor by turning the knob of a potentiometer, using an EasyDriver board.  The control part is solved.  My problem is that if I quickly turn the knob to one end of its range and then back, the stepper motor lags behind by about 1/5 of a second.
All the spec sheets for the motor says I should be able to expect a lot more responsiveness (based on max RPM, acceleration, etc...). I'd like to speed up the responsiveness of the motor to shorten the lag. My code is as follows:
//Declare pin functions on Arduino
#define stp 2
#define dir 3  //LOW => forward, HIGH => backward
#define MS1 4
#define MS2 5
#define EN  6

//Declare variables for functions
int x;
int const potPin = A0;
long potval; // current analog read of A0 voltage
int potrotsteps = 166; //num of stepper motor steps for 300-degree rotation
int cur_step_pos = 0; //current position in terms of stepper steps
long cmd_step_pos = 0; //step-position to command stepper motor to go to
int tomove; //num steps to move

void setup() {
  //stepper motor setup
  pinMode(stp, OUTPUT);
  pinMode(dir, OUTPUT);
  pinMode(MS1, OUTPUT);
  pinMode(MS2, OUTPUT);
  pinMode(EN, OUTPUT);
  resetEDPins(); //Set step, direction, microstep and enable pins to default states
  Serial.begin(9600); // initialize serial communication at 9600 bits per second
  Serial.println("\n\n\n#################    setup completed     #################");
}

void loop() {

  //map analog voltage read from pot to a step-position (0-166) of the stepper motor
  potval = analogRead(potPin);
  cmd_step_pos = potval * potrotsteps / 1023; // find where stepper motor should be in terms of step-position
  tomove = abs(cur_step_pos - cmd_step_pos);

  if (cmd_step_pos > cur_step_pos) { //if should-be position greater than current position
    digitalWrite(dir, LOW); // move forward
    CommandStepperMotor(tomove); //move forward by the diff in position
  } else { //if should-be position is lower
    digitalWrite(dir, HIGH); //move backward
    CommandStepperMotor(tomove); //move backward by diff in position
  }
  cur_step_pos = cmd_step_pos; //current position is now former should-be position

}

//GLOBAL FUNCTIONS

//Reset Easy Driver pins to default states
void resetEDPins() {
  digitalWrite(stp, LOW);
  digitalWrite(dir, LOW);  //default "forward" movement
  digitalWrite(MS1, LOW); // L-L => full steps, H-L => 1/2 step
  digitalWrite(MS2, LOW); // L-H => 1/4 steps, H-H => 1/8 step
  digitalWrite(EN, LOW); //Enable motor control
}

void CommandStepperMotor(int numsteps) {
  for (x = 0; x < numsteps; x++) {
    digitalWrite(stp, HIGH); //Trigger one step forward
    delay(1);
    digitalWrite(stp, LOW); //Pull step pin low so it can be triggered again
    delay(1);
  }
}

I understand that changing delay(1) to delayMicroseconds(100) in the CommandStepperMotor function should help, but as it turns out, anything smaller than a delay of 1 millisecond stalls the motor.  I've tried to Google other's solutions to the problem, but it seems they had no problem at all lowering the delay in sending the HIGH/LOW signals to the stepper pin to <1 ms.
Any ideas?  Thanks in advance!

Your problem is that you want to go from a standstill to full speed instantly. That just isn't going to happen. As you have seen there is a limit to how fast you can go from stationary.
If you want to go faster you will have to accelerate up to that speed.
The simplest way to do that is to use a library that is designed for it, such as the popular AccelStepper.h library.


text:
Writing to flash memory fails with Optiboot
I am having some issue writing to flash memory on Arduino Uno.
I burned the optiboot bootloader that ships with the IDE 1.8.3 to the chip, then uploaded the test_dospm sketch to write content to flash memory but appears to reset the device instead.
Any idea why this might be happening?

The bootloader which ships with Arduino IDE is version 4 which was already in the Uno from factory. To use the do_spm function you need Optiboot 8 build with this support enabled. It is not enabled in the default builds, because it doesn't fit in the usual Optiboot size for Uno.
The hex file of the bootloader is here. Simply replace the hex file in AVR boards package with this one.

I can add more details or even build and test the bootloader and provide boards.txt settings since I have this on my TODO list.

Thanks @Juraj, that would be helpful! I am currently diving in the source code/makefile to see what are the option I need to enable to build the bootloader and you were right about the do_spm not being enabled by default.

@FallaCoulibaly, I discovered that do_spm is in the normal build of Optiboot8. BIGBOOT is not required. I modified the answer.

Thanks, that did the trick

but if somebody ever needs the big version of Optiboot including my copy_flash_pages function, here it is https://github.com/jandrassy/my_boards. about copy_flash_pages: https://github.com/Optiboot/optiboot/pull/269


text:
How to pass a changing value to a graphic display using Arduino?
I am using an EA DOGM132-5 graphic display, they also have provided a library for Arduino, so everything is nice and easy. The library has a function for easily passing a string to the LCD.
void dog_7565R::string(byte column, byte page, const byte *font_adress, const char *str)
{
unsigned int pos_array;                                         //Postion of character data in memory array
byte x, y, column_cnt, width_max;                               //temporary column and page adress, couloumn_cnt tand width_max are used to stay inside display area
byte start_code, last_code, width, page_height, bytes_p_char;   //font information, needed for calculation
const char *string;

start_code   = pgm_read_byte(&font_adress[2]);  //get first defined character
last_code    = pgm_read_byte(&font_adress[3]);  //get last defined character
width        = pgm_read_byte(&font_adress[4]);  //width in pixel of one char
page_height  = pgm_read_byte(&font_adress[6]);  //page count per char
bytes_p_char = pgm_read_byte(&font_adress[7]);  //bytes per char

if(type != DOGM132 && page_height + page > 8) //stay inside display area
        page_height = 8 - page;
  else  if(type == DOGM132 && page_height + page > 4)
    page_height = 4 - page;

//The string is displayed character after character. If the font has more then one page,
//the top page is printed first, then the next page and so on
for(y = 0; y < page_height; y++)
{
    position(column, page+y); //set startpositon and page
    column_cnt = column; //store column for display last column check
    string = str;             //temporary pointer to the beginning of the string to print
    digitalWrite(p_a0, HIGH);
    digitalWrite(p_cs, LOW);
    while(*string != 0)
    {
        if((byte)*string < start_code || (byte)*string > last_code) //make sure data is valid
            string++;
        else
        {
            //calculate positon of ascii character in font array
            //bytes for header + (ascii - startcode) * bytes per char)
            pos_array = 8 + (unsigned int)(*string++ - start_code) * bytes_p_char;
            pos_array += y*width; //get the dot pattern for the part of the char to print

    if(type != DOGM132 && column_cnt + width > 128) //stay inside display area
                width_max = 128-column_cnt;
    else if(type == DOGM132 && column_cnt + width > 132)
       width_max = 132-column_cnt;
            else
                width_max = width;

            for(x=0; x < width_max; x++) //print the whole string
            {
                spi_out(pgm_read_byte(&font_adress[pos_array+x]));
                //spi_out(pgm_read_byte(&font_adress[pos_array+x])); //double width font (bold)
            }
        }
    }
    digitalWrite(p_cs, HIGH);
}
}

So I just use the function in the sketch with the variables I want and I can easily show a string, but I want to show a changing value for example a temperature reading Tc.
int ThermistorPin = 0;
int Vo;
float R1 = 10000;
float logR2, R2, T, Tc, Tf;
float c1 = 1.009249522e-03, c2 = 2.378405444e-04, c3 = 2.019202697e-07;

Vo = analogRead(ThermistorPin);
R2 = R1 * (1023.0 / (float)Vo - 1.0);
logR2 = log(R2);
T = (1.0 / (c1 + c2*logR2 + c3*logR2*logR2*logR2));
Tc = T - 273.15;

But the string function doesn't support variables. Can someone help me to adjust the string function to take variables or perhaps suggest a better way altogether?

You didn't mentioned how you convert the floating point value Tc to  a string before passing it to dog_7565R::string, but if you are using sprintf(), by default Arduino has the sprintf() support for floating point turn off, there is a way to turn it on if you are using Platform.io IDE, but it will not work for Arduino IDE.
One workaround is to use the dtostrf() function available in the avr-libc that is accessible in Arduino:
dtostrf(floatvar, StringLengthIncDecimalPoint, numVarsAfterDecimal, charbuf);

The dtostrf() converts a float to a c string.
float Tc = T - 273.15;
char floatString[6];
dtostrf(Tc, 4, 2, floatString);

This will turn a value like 32.15 into a string "32.15".

dtostrf() is deprecated, which is why I did not include it in my answer.

Thank you, the dtostrf() function works for me, perhaps later I will find a different solution, but for the time being I have just what I wanted!

@selectstriker2 I'm not aware that dtrostrf() is deprecated? It certainly didn't marked as deprecated on avr-libs documentation, and it is even implemented in ARM version of ArduinoCore-samd for backward compatibility reason.

https://github.com/arduino/ArduinoCore-API/issues/103 and https://github.com/arduino/ArduinoCore-API/tree/master/api/deprecated-avr-comp/avr

@selectstriker2 I think you misunderstood it, when you use those functions, it used to have to explicitly write #include <avr/xxx.h> to use it, it no longer the case. What Arduino did is to include those as part of Arduino Core-API that all platforms must compliant and implemented as its core, e.g. ESP32/8266 or STM32, See https://github.com/arduino/ArduinoCore-avr/commit/06df3bb3ed3c342c448eda2a1e02a5346daebcb0, it also marked "deprecated" those files, the word "deprecated"  is misleading, it just relocated.

That would make more sense. I haven't worked with Arduino in a while and anything I searched for recently said that it had been deprecated.

You have to first convert the floating point value to a string, then pass the resulting string to the dog_7565R::string() function.
It looks like the standard sprintf() provided by Arduino does not support the %f format for floats, so you may have to find another way to convert it or write your own conversion function.


text:
Having trouble with sprintf function and string class
in my code, I was using string class to make an array to store my menu items
String menu[2] = {{"Menu 1"}, {"Menu2"}};

How do I convert this into char arrays and how do I call them?
Example:
Serial.println(menu[0]);

Sounds like you're looking for menu[0].c_str()

const char* menu[2] = {"Menu 1", "Menu2"};

By the way, you can access a string.  You call a function.  You don't call a string.

Create them as char arrays like this:
const char* menu[2] = {"Menu 1", "Menu 2"};

and use them like this:
Serial.println(menu[0]);

Strictly speaking it's an array of char*, not an array of char. And you should handle "Menu 1" as a const char*, to allow the compiler inhibit you doing nonsense. And avoid warning: ISO C++ forbids converting a string constant to 'char*' [-Wwrite-strings]

Edited for the const.

It is an array of char*.  And each one of those pointers points to a char array, not a String.  My point there was to distinguish between char array and String object.

Agreed. Even the warning text calls "hello" a string constant. But string (string literals aka const char array) and Arduino String Objects are so different that we should avoid using the term string completely.


text:
3,6V DC motor spinning with L298N and Arduino
I'm trying to control a re used DC motor from a drill (3,6V) with a L298N and a Arduino. It's powered with a 5V - 60A power supply.
I tried to follow this step by step tutorial (https://www.youtube.com/watch?v=dyjo_ggEtVU) but the motor is not spinning..yet. I can ear a noise, it starts to spin a micron and then stops.
I though that it could be something wrong with the power supply but I connected the 4V battery from the drill and the same thing is happening. If I connect the motor directly to the battery it is spinning nicely...
I though then that it was a code issue but I tried a no load test and measured the voltage without the motor -> I've the 4V required voltage. When the motor is connected I have 300mV instead of 4V.
Do you know what could go wrong? Is the L298 dead? just got it a few hours ago...
Would be nice if you have any clue.
Many thanks.
// Commande moteur
    int enA = 9;
    int in1 = 8;
    int in2 = 7;
void setup()
{
  // Définition des sorties

  pinMode(enA, OUTPUT);
  pinMode(in1, OUTPUT);
  pinMode(in2, OUTPUT);

  //Sens de rotation du moteur

  digitalWrite(in1, LOW);
  digitalWrite(in2, HIGH);

  //Vitesse de rotation du moteur

  analogWrite(enA, 200);

  //Delay

  delay(5000);

   //Arrêt du moteur

  digitalWrite(in1, LOW);
  digitalWrite(in2, LOW);
}

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

}

The L239 is a terrible motor driver. It's the kind of motor driver Noah used to control The Ark.
It requires a power supply that is at least 2.5V more than the "logic input high" voltage, which is rated at 2.3V. That means an absolute minimum of 4.8V, which is borderline for the Arduino's 5V pin, especially if you are running off USB (which can drop as low as 4.75V and still be within specification) and way out when powered from the battery.  It's really designed for driving motors in the 12V+ range.
To drive a low voltage motor like yours you need to pick a more modern MOSFET based motor driver.

Thanks for the feedback, what if I use a 12V power supply and I use the AnalogWrite to drop the motor voltage to 4V?

It might work... until that fateful day when you accidentally send 12V straight to the motor...

I'll try that...  thanks :)

I tried with a 20V DC power supply and it's not going to work because analogWrite(pin,1) gives me a minimum of 12V DC at the motor.

Then you should get a proper motor driver that is suitable for your motor, or get a better motor that is suitable for your power supply. Matching your components to your needs is step one of learning to be an electronic engineer...


text:
Atmega32A fuses
I have Atmega32A and 16 MHz quartz, with 22pF capacitors. Tell me, please, how to set the fuses correctly so that the MK works from external quartz.
Will MK work when setting 0xFF LOW and 0xD8 HIGH? These are the fuses of the Arduino Leonardo
As a result, I want to get a working microcontroller with work from external quartz and that I could rewrite the program.
I use eXtreme Burner - AVR and usbasp

have you searched for a fuse calculator on the internet?

Yes. I already set 0xFB LOW and 0x99 HIGH. After that, my microcontroller does not respond. As with the JP3 jumper on usbasp and without it.

@ОлегС So you've used "Low Freq" Crystal/Resonator... No wonder it's not working with High Freq Crystal

@ОлегС what exactly is your question? ... your post asks how to set fuses, but then your comment says that you already set the fuses

@KIIV And what is the difference between Low Freq 16K CK and High Freq 16K CK?

@jsotola Probably my question is incorrect. Sorry. I just wanted to know how to properly set the fuses, so as not to spoil the next microcontroller.

@ОлегС it's usually weaker driver

This Atmel fuse confuses me a lot so I have figure out an easy way of finding fuses for such controllers basically two methods that I have used once are:
Method 1:(explaining specific for this controller (
    ATmega1284,
    ATmega644,
    ATmega324,
    ATmega164,
    ATmega32,
    ATmega16,
    ATmega8535
))
Add this to your Arduino board manager it is from MCU dude they have different varients also for other controllers check here.
Now select your controller and your clock frequency and all parameters as you like after that use USBASP or Arduino as isp for burning bootloader inside your controller, in this case, we will burn the bootloader into Atmega32A.
After the successful burning bootloader, you will need an AVRdudess software by using this software you have to just read the fuse of our MCU so we will get the fuse setting done by MCUdude from Arduino and after that, you can directly set those fuse setting and it will work fine.
Method2:
just use online calculators such as here for finding fuse settings.


text:
Workflow when using Emacs, Arduino-makefile and Serial monitor?
I'm trying to develop code, compile, upload and use the Serial monitor for debugging of a script for an Arduino Pro Mini. I'm using Emacs as my IDE. I'm having trouble determining the exact sequence of commands to do this most efficiently. What I'd like to do is:

Edit my code, compile and upload from Emacs (able to do this now)
Switch to a window running minicom (or putty, etc.) and observe the debug output.
rinse and repeat

My problem is that now, I have to stop and start minicom each iteration, after I upload the code. Sometimes, restarting minicom causes my Arduino to reboot, and that then displays the debugging output correctly. Sometimes, it takes two minicom restarts to accomplish this. Also, if I don't kill minicom before uploading, it just prints garbage to the screen, and seems to hang. I'm hoping for something like the Arduino IDE Serial monitor, that just runs continuously, and that correctly displays the debugging output.
Ideally, I'd like help coming up with the exact commands to run a Serial monitor that wouldn't require stopping and starting it. Is this possible?
Thanks for all your suggestions and advice.
-Kevin

that is the advantage of the Serial Monitor in IDE. IDE disconnects it before upload and connects it back after upload.

There's no way to disconnect and reconnect minicom remotely. All you can do is kill the process, and then manually restart it.


text:
Alternatives to Nextion display
I am wanting to have a display where I can design the GUI on a program and then somehow transfer it to the display. For the graphics I want to make, it would be really hard to manually write the code. I heard that the Nextion displays do this but they are quite costly. Is there some cheaper alternative? If not, can you make a normal display do all of that?

The only other make I know are 4D Systems, and they are just as much, if not more, than Nextion.

We work with Proculus displays, and we are a distributor of this display here in Brazil (Victor Vision). The display is great, very professional. Used in medical equipments, and cheaper than Nextion.
They are starting now in the web and selling in Alibaba.


text:
Use Android on Arduino TFT
I don't know whether this is possible or not but is there any way that I can run something similar to Android on a normal TFT. I want to make complex graphics but can't program those complex programs using the Adafruit TFT library.
Arduino Mega 2560 with Elegoo TFT 2.8"

a TFT is just a display ... it does not run code

start at the begining ... write a sketch that displays a full screen image on the TFT  ..

As jsotola says, start simple. Learn to draw lines and rectangles and such. Then learn how to combine those into the graphics that you want. The problem with "fancy" graphics is that they are generally big - based around bitmap images, which the Arduino can't handle well. You need some extra storage (flash chip, SD card, etc) to store them. Maybe learn how to display bitmap images from SD card would be a good step.

No. Not even remotely. Android runs on a powerful computer not a tiny embedded microcontroller.


text:
DIY CNC Machine Power Requirements
I want to make a CNC machine that uses 5 NEMA 17 rated for 2A and a RAMPS 1.4 to control it all. I have a power supply that can deliver 1.5A at 12V. Is it enough? I am worried that when all 5 motors are under load, the amperage will get distributed and there will be very low amperage per motor.

5x2 is 10. You need at least that and more.

So I need at least 10 amps!

Is there any cheap place I can get that type of power supply? Also how much can an ATX power supply give out?

Yes, and more than that - here's an example https://cpc.farnell.com/unbranded/500w-builder-black/500w-black-12cm-psu-pfc/dp/CS32144?mckv=saBqmjUHB_dm|pcrid|395592567287|kword||match||plid||slid||product|CS32144|pgrid|83089512472|ptaid|pla-781001870297|&CMP=KNC-GUK-CPC-SHOPPING&gclid=Cj0KCQiA7qP9BRCLARIsABDaZzj6FBitKJ-pzTDlGUG-ci5LeuKl5bZcNUPqsTcVxTOlGW2Q3VvgLxoaArTlEALw_wcB

You can limit the current on some stepper driver modules by adjusting a potentiometer. But that results in less torque in the stepper motor. Not ideal, but it might be useful, so you can move forward while waiting for a proper power supply.

PS on ATX power supplies to need to connect the green wire (PS_ON) to GND (black wire), to enable it.

Some also need a load on the 3.3v or 5v to operate.

Is there near the 5-10 USD range?

Here's one that's $14.50. I'm personally not a fan of using ATX power supplies as general power supplies. Mornsun isn't a very known brand
but we using them for all our power supplies at my company and they are just as good for the faction of the cost. https://store.nacsemi.com/products/detail?part=LM150-20B12&stock=MS000000009106

Figuring out your current needs is simply a matter of adding everything up. If you have 5 2 amp motors, you'll need 5 x 2, or 10 amps just to drive the motors.
You should probably have at least 20% extra capacity, so I'd suggest having a 12V power supply that can put out at least 12A.
15A would be better.
The stiffer your power supply the less it will "bobble" as the load varies.

That's not really how stepper motors behave in practice, since their rated currents occur at much lower voltages than Vcc under use.
5A should be fine for five such steppers.


text:
Arduino Voltage Reading Problem
I was trying made a gear indicator for my bike, with manually sensing the gear shift.  But failed, cause my bike has no separate "neutral" wire, instead there is gear sensor in-built...!! But not gear-position indicator...!!
The in-built sensor gives different output voltage at every gear.
It sounds good that all I need is just an Pro-mini & OLED.
But, facing problem with the voltage reading on Pro-mini.
When I checking with normal multimeter, the output voltage is very stable.
I tried with the simple voltage reading code.
And added the voltages ranges as shows on multimeter.
Later Checked with Uno, Reading is quite stable (+- 0.02V).

But, Pro-mini voltage reading is too sensitive.
Sometimes, in same gear position getting high voltage difference.
So, in result I doesn't getting a stable voltage reading or gear display.

Need suggestion to make changes, so the pro-mini also read like the multimeter / Uno reads.
(Is this because of Pro-Mini doesn't have the Op-Amp in-built?)

And, also, Why the serial output is around 1.5V, while no input in A0...?

PS: I didn't use voltage divider, because, gear sensor output voltage is below 5V.

That shouldn't happen. I assume it's a 5V 16Mhz Pro mini. Make sure power doesn't go through the voltage regulator on the Pro Mini. Try a different Pro Mini. Try a different analog pin on the Pro Mini. Try out the UNO again, to make sure the sensors signal still stable. You could try averaging the results to get a more stable value, but that's more something you'd do if the signal isn't very stable.

Okay, now that's very quick... After searching & trying over weeks... Just changing the Analog pin works perfectly. (-_-) Feeling Dumb... Anyway, thank you very much...!!!

Another Question, The output gives around 1.5V without any input... Should I use 10K pull-down... or subtract that in programming?

as long as you get discrete values for each gear, i wouldn't try to rebalance the equation.

Ok. It stable, for no input at analog pin... But when I add the sensor output to A1, its again unstable. I connected multimeter & arduino together, no issue with multimeter, but the Pro-mini reading is messed up...!!!!!!

It's all OK now... I was using different grounds... After attaching it fully on bike power, it's working like charm... Thank you guys...


text:
About ATTINY85 Development Board
I am thinking to buy one of "ATTINY85 Development Board"...
Before buying I was checking details/Advantages of it.

First I thought this is just a breakout board & USB for power.
But, then found It can be programmed with "Digispark driver & board manager" directly by the USB.

I checked this Question: EBay “Development Programmer Board for ATtiny”
Someone said there:

"While limited, this type of board can be useful for "blink an LED on
  USB command" type tasks"

My Main question is:
Is it really programmable withut any TTL/ICSP/FTDI extention?
If so, is it possible to program other AVR chip (Attiny/Atmega) with simple codes directly via USB...?
(with same method)

Is it really programmable withut any TTL/ICSP/FTDI extention?

Only if you use an ATTiny chip that has the "Micronucleus" bootloader already installed.

If so, is it possible to program other AVR chip (Attiny/Atmega) with simple codes directly via USB...?

Some can, but most need a bootloader installing. The ATMega32U4, for example, has a "DFU" mode, which is essentially a bootloader in ROM, that you can use directly over USB.  In general, though, the answer is "Not without installing an appropriate bootloader with some hardware programmer first".

Thanks... Now it makes sense... Because most of the tutorials doesn't told about "bootloader" part, maybe the soldered MC already has it... At last found a video with best review & tutorial YT link


text:
Transmit datastring using SIM7600 4G hat
I've been using Adafruit Fona with SIM800 chip to transmit data through the phoneline. SIM800 is a 2G chip but this network is closed in Norway so now I bought a Waveshare SIM7600 hat for Arduino instead. When using Fona I set up the call with this command: "ATDphonenumber" and when the connection was established I got this message: "CONNECT 9600". Then Fona went into data mode and I could send and receive datastrings before returning to command mode using +++. On the SIM7600 I need to write the call-command this way: "ATDphonenumber;" and the respond is "BEGIN: VOICE CALL" when connection is established. The problem is I can't get into datamode. The manual says use this AT command: "ATO" but that gives me "NO CARRIER" in return.
Now I wonder how I can make a call to another device and be able to send datastrings just like using Fona.

LTE doesn't have a "data mode". It's a direct internet connection. Set up the APN for your carrier and start a session, then you can make TCP and UDP connections directly.

OK, that makes it all more clear. I will check out that. Thank you so much for your reply!