Arduino code - florindumitrescu94/DashBoard_PowerBox_V2 GitHub Wiki

Introduction

Prerequisites

Now, that we have built the device, we need to program the Arduino, so it can communicate with the computer.
For this, we will need to install the Arduino IDE found here. Download the most recent Arduino IDE Version.

After downloading and installing the IDE, you will need to install the DHTStable.h library from the Library manager. Go to Sketch > Include Library > Manage libraries, then search "DHTStable". Install the most recent version (1.1.2 as of the time I am making this tutorial).

You might also need to install CH340 drivers. If you are running Windows 11, you might have trouble connecting an older version of the Nano board, so you can go here and look for the most recent drivers.

Code explanation

There are some functions that I feel I need to explain the way they funciton. What has not been explained here is fairly straightforward and can be understood easily by checking the code.

PWM automation function

This function runs in a loop and sets the values of the PWM output based on a few factors.
// RUN PWM AUTO
void RUN_AUTO_PWM() {
if (HUM_REL>50) DP_OFFSET = ((HUM_REL/10)-5);

This section of the code will determine the agresivity of the dew heater automation, based on the relative humidity recorded by the DHT22 sensor. Basically, the higher the humidity, the higher the probability of your optics dewing up. The power is set so that the temperature recorded by the NTC probes is 2 to 5 degrees higher that the Dew point. Since we want to avoid our optics dewing up, we will artificially increase the dew point temperature, as the humidity increases, by a number between 0 and 5. To make an easy corelation between this offset and the humidity, we can divide the humidity by 10, to get a single digit number, then subtract 5 from it (since we want the offset to start at 50% humidity and only go up by 5 degrees at most).

if(PWM_AUTO == 1) // Checks pwm auto flag. If set to 1, then the code will run.
{
if (timetotal_ntc > 1023) // As changing the power to the dew heater does not render an immediate rise in temperature, we want to give it some time before checking again. A count to 1023 is an adequately long time for the temperature to increase.
{
if (NTC1_VALUE > -40) { // If a probe is not connected, the value displayed will be -40. This will disable the automation for that PWM port.
if (NTC1_VALUE - (DEWPOINT + DP_OFFSET) < 2 && PWM1_STATE < 100) // Checks the difference between current dew heater temperature and current dew point + offset. If lower than 2 degrees, runs (only if PWM power is lower than 100%) {
PWM1_STATE = PWM1_STATE + 5; // Adds 5 to PWM power (0-100)
PWM1_STATE = CORRECT_PWM(PWM1_STATE); // CORRECT_PWM(value) sets the value to 0 if value is negative, or to 100 if value somehow goes over 100.
SET_PWM_VALUE(1,PWM1_STATE); //Sets the new value to the PWM port } if (NTC1_VALUE - (DEWPOINT + DP_OFFSET) > 4 && PWM1_STATE > 0) // Checks the difference between current dew heater temperature and current dew point + offset. If higher than 5 degrees, runs (only if PWM power is higher than 0%)
{
PWM1_STATE = PWM1_STATE - 5; // Removes 5 from PWM power (0-100) PWM1_STATE = CORRECT_PWM(PWM1_STATE); // CORRECT_PWM(value) sets the value to 0 if value is negative, or to 100 if value somehow goes over 100.
SET_PWM_VALUE(1,PWM1_STATE); //Sets the new value to the PWM port
}
----CODE REPEATS FOR NTC2 / PWM 2-----
timetotal_ntc = 0; // If the counter has reached 1024, it will reset it back to 0
}
timetotal_ntc += 1; //Increments the counter by 1 for each function run
} else if (PWM_AUTO == 0) timetotal_ntc = 0; //Resets the counter to 0 if the PWM automation is turned off
}
//END SET AUTO PWM POWER `

Measuring voltage, current, power and total power consumption

Since we are dealing with mostly PWM controlled power, calculating the current usage without implying a means to average out the readings will yeld to very jumpy and innacurate results. Therefore, I have implemented an array that gets updated over time, then average the sum of all the values in the array to obtain the average current usage over 150 cycles. The GET_POWER() function runs in a loop everytime.

To determine the total power consumption since device has been connected, we need to measure the total power consumption in W*h per each cycle, then add that up to a total. Since the Arduino Nano floating point only allows for 2 decimals of precision, we need to first calculate the power in milliseconds, then divide that power by 3600000 (number of milliseconds in an hour).

//MEASURE AND CALCULATE POWER USAGE
void GET_POWER() {
time1=millis(); //records time when function starts
if (AVERAGE_COUNT == 150) AVERAGE_COUNT = 0; // Resets the average counter used as an array index to average current consumption over 150 cycles.
float VOLTAGE_SAMPLE_SUM=0; for (int v=0;v<150;v++) { PIN_VALUE_V = analogRead(VM); VOLTAGE_SAMPLE_SUM +=PIN_VALUE_V;
} VOLTAGE_SAMPLE_SUM /=150; VOLT_TEMP = (VOLTAGE_SAMPLE_SUM * 5.0) / 1024.0;
VOLT = VOLT_TEMP / 0.0982; // Tune this last number (VDIV ratio) until it will show the correct voltage (compare by reading the voltage with a voltmeter)
if (VOLT < 0.1) VOLT=0.0;
CURRENT_SAMPLE_SUM=0; // Resets the sum of all the samples gathered in the next step for (int i=0;i<150;i++)
{
PIN_VALUE_A= analogRead(AM);
CURRENT_SAMPLE_SUM = CURRENT_SAMPLE_SUM + PIN_VALUE_A; //Gathers 150 readings from the A1 pin
}
AMP_AVERAGE[AVERAGE_COUNT] = (ACS_Bias - ((CURRENT_SAMPLE_SUM/150)(5.0/1024.0))) / ACS_resolution; // Calculates the current for the current cycle, then sets the current array value.
AVGAMP=0; //Resets the variable, as it is later used to sum up all the values in the AMP_AVERAGE array.
for (int c=0;c<150;c++) AVGAMP += AMP_AVERAGE[c];
AMP = AVGAMP/150;
if (AMP< 0.01) AMP=0.0;
PWR = VOLT * AMP;
AVERAGE_COUNT = AVERAGE_COUNT + 1;
time2=millis(); //records time when function ends
PWR_TOTAL_S = PWR_TOTAL_S + ((PWR
(time2-time1))/1000); // total power in Ws
PWR_TOTAL = PWR_TOTAL_S/3600; // Total power used in W
h
}

Prepare code

After all the prerequisites are installed,either download the arduino file or create a new Arduino sketch and, copy the code from the DashBoard_PowerBox_V2.ino file and paste it in your sketch.

Now it's time to make some changes in the code to fit your components.

Since the Arduino nano's floating and double types can only hold 2 decimals and our formulas need 3 or more decimals, we will need to change some numbers directly in the code (we can't use constants and then divisions, since we will only get two decimals and the readings will be off).

First,we need to set the voltage divider ratio by taking the values we have previously measured for vdiv_10k and vdiv_100k and dividing vdiv_10k by vdiv_100k. We should get a number of around 0.1, but if the number is lower or higher, use 4 decimals from the number you got .(example: 0.0982). We might not obtain the right voltage right away, so we can tune this value until we obtain the correct voltage reading as measured by a voltmeter.

Then, we need to set the beta value and the nominal resistance of our NTC probes in the ntc_beta and ntc_ohm constants. Mine have a beta value of 3380 and 10k at 25C. If yours are different (usually, the place you buy the probes will mention the beta value and nominal resistance), you need to change these values with the correct ones for the probes you bought.

Now, we set the values for ref_ohm1 and ref_ohm2 constants, as previously measured.

Lastly, we need to set the correct variant of the ACS Sensor and tune the reading. This will determine the resolution of the current reading (but also the headroom) and ensure accurate reading.

Tuning ACS reading.

Since all components have a margin of error, the ACS sensor will have one, too. The line in the code that calculates the current is this:
AMP_AVERAGE[AVERAGE_COUNT] = (2.494 - ((CURRENT_SAMPLE_SUM/150)*(5.0/1024.0))) / ACS_resolution;

Notice the first number in this formula.

Since the ACS712 sensor can read both positive and negative currents, the bias voltage (the voltage that comes out of pin 3 of the chip) is roughtly 2.5V. As we have mounted the chip so that the current flows from pins 3 and 4 to pins 1 and 2, the voltage output on pin A1 will decrease as the current increases. Therefore, we need to subtract this value from the bias voltage to get the correct current value. However, due to manufacturing errors and component tolerances, this bias voltage will not always be exactly 2.5V.
As this can offset the current reading, we need to measure and tune this value so that the current reading 0 when no current flows through the sensor.
To do this, we can measure the voltage coming out of pin 3 with a precise voltmeter and replace this value with the measured one.

Uploading the code

Connect the board

Once the code has been prepared, we can upload it to the Arduino board. Connect your Arduino to the computer using a USB cable. In the Arduino IDE, click on the Boards list and select the "Unknown" option.

image

Once the pop-up window appears, search and select Arduino Nano from the list and select the correct COM port.

image

In the Tools tab, you should see these selections:

image

Press the Compile button first to check for any syntax errors in the code, then click Upload.
Once completed, the message at the bottom should say Done Uploading.

Error uploading

You might have some errors when uploading the code.

DHTStable library is not found.

You need to install the DHTStable library (please see the Prerequisites section of this page). If you've already installed the library, try to restart the Arduino IDE, or install a different version.

Upload timed out

There might be a chance that your board uses the Old Bootloader. In this case, you need to tell the Arduino IDE to use the Old bootloader by selecting it here, in the Tools tab:

image

Error uploading to the board

If you get this error, you might have something else connected to that COM port, or you have selected an incorrect COM port. A situation I have encountered is that, whenever I have Cura open, it somehow blocks the port my Arduino is connected to, possibly because my 3D printer has the same COM port assigned to it. Tried closing all other applications, check the COM port and try again.

To easily determine which COM port your Arduino is connected to, open Device Manager and expand the Ports (COM & LPT) section. Then disconnect your Arduino. Note which COM port has dissapeared. Connect it again and note the new COM port. That will be your Arduino's COM port.

image