PWM outputs and convertion to analog

Hello,
I am trying to build and weather station and convert the measurements to analog voltages. I am using the DS15901 kit and the ADSWeather library.
I am using one arduino nano to collect measurement, which communicates, by i2c, with a second one to convert these measurements to pwm signals. I use 2 arduino because to collect measurements library uses interrupts, which interference with pwm.
The part about collecting measurements succeeded.
The problem I face is for the conversion to analog voltage. I am using the LM358 op. amp. the circuit working well.
I use digital pin 5, 10 and 11 so the pwm signal comes from different timers, but analogWrite to one pin seems to interferece with analog write of the other pin, producing wrong outputs.
I am struggling with this 2 weeks now and I cannot find the problem. Can anyone help me.
I am attaching the code and the schematic.
Thanks in advance

#include <Wire.h>

#define ANEMOMETER_SPEED_OUT_PIN 5 

#define RAIN_PIN_OUT 10
#define VANE_OUT_PIN 11


#define CALC_INTERVAL 1000

unsigned long nextCalc;
unsigned long timer;

long windSpeed = 0;
long windDirection = 0;
float rainRate = 0;
long windSpeed_last;
long windDirection_last;
float rainRate_last;


//int windDir;
//int windSpeed;
int windSpeed_analogWrite = 0;
int vane_analogWrite = 0;
int rain_analogWrite = 0;
int RainBoolState;
char i2c_response[16];

void setup() {
  Wire.begin(); // join i2c bus (address optional for master)
  Serial.begin(9600);
  pinMode(ANEMOMETER_SPEED_OUT_PIN, OUTPUT);
  analogWrite(ANEMOMETER_SPEED_OUT_PIN, 0);
  pinMode(RAIN_PIN_OUT, OUTPUT);
  analogWrite(RAIN_PIN_OUT, 0);
  pinMode(VANE_OUT_PIN, OUTPUT);
  analogWrite(VANE_OUT_PIN, 0);

  windSpeed_last = windSpeed;
  windDirection_last = windDirection;
  rainRate_last = rainRate;

  nextCalc = millis() + CALC_INTERVAL;

}

void loop() {
  timer = millis();

  if (timer > nextCalc)
  {
    nextCalc = timer + CALC_INTERVAL;
    memset(i2c_response, '\0', 15 * sizeof(char)); //clear i2c response

    //ask for weather data form data collector on address 8 using i2c
    Wire.requestFrom(8, 16);    // request 16 bytes from peripheral device #8
    int i = 0;
    while (Wire.available()) { // peripheral may send less than requested
      char c = Wire.read(); // receive a byte as character
      i2c_response[i] = c;
      i++;
      //      Serial.print(c);         // print the character
    }
    Serial.println(i2c_response);         // print the character
    windSpeed = (i2c_response[4] - '0') * 100 + (i2c_response[5] - '0') * 10 + (i2c_response[6] - '0');
    windDirection = (i2c_response[0] - '0') * 100 + (i2c_response[1] - '0') * 10 + (i2c_response[2] - '0');
    rainRate = (i2c_response[8] - '0') * 10 + (i2c_response[9] - '0') + (i2c_response[11] - '0') * 0.1 + (i2c_response[12] - '0') * 0.01;
    RainBoolState = i2c_response[14] - '0';
    //    rainRate=80.2;
  }


  //we are going to convert max of 75km to analog output
  if (windSpeed > 0 && windSpeed < 5) {
    windSpeed_analogWrite = 50;
  }
  if (windSpeed >= 5 && windSpeed < 10) {
    windSpeed_analogWrite = 100;
  }
  if (windSpeed >= 10 && windSpeed < 30) {
    windSpeed_analogWrite = 150;
  }
  if (windSpeed >= 30 && windSpeed < 50) {
    windSpeed_analogWrite = 200;
  }
  if (windSpeed >= 50 && windSpeed <= 75) {
    windSpeed_analogWrite = 254;
  }


  //we are going to convert max of 50mm per hour rain to analog output
  if (rainRate <= 0 || rainRate >= 75) {
    rainRate = 0;
    rain_analogWrite = 0;
  }

  if (rainRate > 0 && rainRate < 5) {
    rain_analogWrite = 50;
  }
  if (rainRate >= 5 && rainRate < 10) {
    rain_analogWrite = 100;
  }
  if (rainRate >= 10 && rainRate < 20) {
    rain_analogWrite = 150;
  }
  if (rainRate >= 20 && rainRate < 50) {
    rain_analogWrite = 200;
  }
  if (rainRate >= 50 && rainRate < 75) {
    rain_analogWrite = 254;
  }
  Serial.print("rain rate raw: ");
  Serial.println(rainRate);
  Serial.println(rain_analogWrite);


  //export voltage in relation with wind direction;
  if ((windDirection >= 315) || (windDirection < 45)) {
    //North
    vane_analogWrite = 50;
    Serial.println("North");

  }
  else if ((windDirection >= 45) && (windDirection < 135)) {
    //East
    vane_analogWrite = 110;
    Serial.println("East");
  }
  else if ((windDirection >= 135) && (windDirection < 225)) {
    //South
    vane_analogWrite = 180;
    Serial.println("South");
  }
  else if ((windDirection >= 225) && (windDirection < 315)) {
    //West
    vane_analogWrite = 250;
    Serial.println("West");
  }

  if (windSpeed_last != windSpeed) {
    windSpeed_last = windSpeed;
    analogWrite(ANEMOMETER_SPEED_OUT_PIN, windSpeed_analogWrite);
  }
  if (windDirection_last != windDirection) {
    windDirection_last = windDirection;
    analogWrite(VANE_OUT_PIN, vane_analogWrite);
  }
  if (rainRate_last != rainRate) {
    rainRate_last = rainRate;
    analogWrite(RAIN_PIN_OUT, rain_analogWrite);
  }

  //     windSpeed / 10 will give the interger component of the wind speed
  //     windSpeed % 10 will give the fractional component of the wind speed
  Serial.print("Wind speed: ");
  Serial.print(windSpeed / 10);
  Serial.print('.');
  Serial.print(windSpeed % 10);
  Serial.print(" ");

  Serial.print("Wind Direction: ");
  Serial.print(windDirection);
  Serial.println("");

  Serial.print("Rain Rate: ");
  Serial.println(rainRate);
  Serial.println("-----");

}

Schematic.pdf (2.0 MB)

Which two pins are cross-talking?

Pin 5 and 10.
When I disable analogWrite on pin 5. Then pwn output on pin 10 is working well.

You don't seem to have any pull up resistors on the I2C lines, and they go nowhere on the schematic.

What sort of Nano do you have? There are six sorts of nano - and counting.

You do not use it like this.
analogWrite will not work with any of the analogue pins. It will only work on the PWM pins. So all your code is wrong and doesn't match the schematic.

1 Like

i2c goes to another arduino nano, messages with the other arduino are transmittedu without problem, so the fault is not there.
Both arduino nano are clones (old boot loader)
B
Pin 5 and 10 are not analog pins, are digital.
Pinmode and analog write commands are copied from pwm sketch examples.
Yeap you are right about the schematic, because it is older version, but again all the pins I used are pwm pins.
Thank you for your time. I would appreciate if you can give me some hint on the problem.

That should not happen. If it is happening then it is probably down to the wiring or the physical layout of the wiring.

Can you tell by how much it is deviating? Have you an oscilloscope to measure these things?
How does this problem manifest itself? In other words how do you know this is happening?

I don't see any filtering on the PWM pins on that schematic to turn it into a voltage?

There is no need to use the pinMode instruction on any pin you want to set to produce PWM.

Thank you for your help.
Finally the problem was a loose ground connection.
@Grumpy_Mike I didn't know that there is no need of pinMode usage when i want to produce PWM, thank you.
I make use of LM358 to convert PWM signals to analog voltage and I use a Shelly uni to measure the output voltage.

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.