RP2040_PV_Panel_Monitor
STDRP2040_PV_Panel_Monitor
License
:CERN Open Hardware License
Description
# RP2040-based Photovoltaic Panel Monitor
# Safety Warning
This project deals with high DCs voltages. Make sure you understand what you are doing. Please read the safety warning below carefully.
# This PCB can monitor the volages and current of up to 8 PV cells with up to 50V each.
Please see https://github.com/GormR/PV_Supervisor for details.
CERN Open Hardware Licence Version 2 - Strongly Reciprocal
--------------------------------------------------------------------------------
# Test code for PV Panel Monitor
#
# copyright 2023 by Gorm Rose
#
# This example code is licensed under GNU PL V3.0
# GP0: MuxSel1
# GP1: MuxSel0
# GP2: Temperature (DS18B20U)
# GP26: AIO0 voltage of "negative" PV modules
# GP27: AIO1 voltage of "positive" PV modules
# GP28: AIO2 common current
# Vref = external
from machine import Pin, I2C, ADC
#from ssd1306 import SSD1306_I2C
from time import sleep
#### µC pin definitions ####
MuxSel1 = Pin(0, Pin.OUT) # select1 for all multiplexers
MuxSel0 = Pin(1, Pin.OUT) # select0 (LSB) for all multiplexers
LED = Pin(3, Pin.OUT) # LED (high = on)
ADCn = ADC(26)
ADCp = ADC(27)
ADCc = ADC(28)
#### user constants ####
factor1 = 3 * (1 * 470 + 24) / (0x10000 * 24) # 3 volt reference, 16 bit, divider 470/24
factor2 = 3 * (2 * 470 + 24) / (0x10000 * 24) # 3 volt reference, 16 bit, divider 940/24
factor3 = 3 * (3 * 470 + 24) / (0x10000 * 24) # ...
factor4 = 3 * (4 * 470 + 24) / (0x10000 * 24)
factor5 = 3 * 1000 * 2 / (0x10000 * (470 + 2))
#### variables ####
# neg _ pos
# P1 P2 P3 P4 P5 P6 P7 P8
Vpv = [0, 0, 0, 0, 0, 0, 0, 0]
Ppv = [0, 0, 0, 0, 0, 0, 0, 0]
Ipv = 0
def set_mux(channel):
if (channel & 2) == 0:
MuxSel1.value(0)
else:
MuxSel1.value(1)
if (channel & 1) == 0:
MuxSel0.value(0)
else:
MuxSel0.value(1)
def read_value(channel, number_of_samples):
global Vpv, Ppv, Ipv
rawVoltNeg = 0
rawVoltPos = 0
rawCurrent = 0
set_mux(channel)
sleep(0.001)
for i in range (0, number_of_samples):
rawVoltNeg += ADCn.read_u16()
rawVoltPos += ADCp.read_u16()
rawCurrent += ADCc.read_u16()
Ipv = factor5 * rawCurrent / number_of_samples
if channel == 0:
Vpv[0] = factor4 * (0x10000 - rawVoltNeg / number_of_samples) - Vpv[1] - 3
Vpv[4] = factor1 * rawVoltPos / number_of_samples
Ppv[0] = Ipv * Vpv[0]
Ppv[4] = Ipv * Vpv[4]
if channel == 1:
Vpv[1] = factor3 * (0x10000 - rawVoltNeg / number_of_samples) - Vpv[2] - 3
Vpv[5] = factor2 * rawVoltPos / number_of_samples
Ppv[1] = Ipv * Vpv[1]
Ppv[5] = Ipv * Vpv[5]
if channel == 2:
Vpv[2] = factor2 * (0x10000 - rawVoltNeg / number_of_samples) - Vpv[3] - 3
Vpv[6] = factor3 * rawVoltPos / number_of_samples
Ppv[2] = Ipv * Vpv[2]
Ppv[6] = Ipv * Vpv[6]
if channel == 3:
Vpv[3] = factor1 * (0x10000 - rawVoltNeg / number_of_samples) - 3
Vpv[7] = factor4 * rawVoltPos / number_of_samples
Ppv[3] = Ipv * Vpv[3]
Ppv[7] = Ipv * Vpv[7]
print("Hello Solar World!")
for i in range(0, 1000):
for j in range(0, 4):
read_value(j, 1000)
print("voltages: ", Vpv)
print("current: ", Ipv)
print("resulting power: ", Ppv)
print()
Comment