Hi All,
I've been working on a project for a while now and I think I'm 95% of the way there.
It's a mosfet and driver circuit with an OLED display.
I want it to be able to self regulate current at a value that will be set via potentiometer.
I'm using a CQ2064 current sensor Data Sheet Here and a 10K pot.
The brains of the operation is the Arduino Every and there is an opto isolated driver for the mosfet connected to pin 3 for PWM.
I don't have all the components to complete the connection to the mosfet but the driver is connected to the Arduino. When I power up, the display works and displays all the values as one would think is correct. Raw Amps reads 0, Volts/Cell read 2.5v but this is not connected, Duty Cycle reads 0% and the Target Amps reads between 7 and 10.
The thing that confuses me during testing is there is 0v on pin 3 regardless of where the target amps are set. If the sketch is correct there should be 5v on pin 3 because there is not enough Raw Amps to meet the Target Amps.
#include <Ewma.h>
#include <Arduino.h>
#include <U8g2lib.h>
#ifdef U8X8_HAVE_HW_SPI
#include <SPI.h>
#endif
#ifdef U8X8_HAVE_HW_I2C
#include <Wire.h>
#endif
Ewma adcFilter1(0.005);
Ewma adcFilter2(0.003);
Ewma adcFilter3(0.005);
byte targetPotPin = A5;
byte voltSensePin = A3;
byte currentSensePin = A0;
byte mosfet = 3;
int targetVal = 0;
int targetPotVal = 0;
int voltageVal = 0;
int dutyCyclePercent = 0;
int dutyCycle = 0;
float target = 0.0;
float targetBuffer = 0.03;
float current = 0.0;
float currentVal = 0.0;
float voltage = 0.0;
float currentForDisplay = 0.0;
float correctedCurrent = 0.0;
const float maxCurrent = 11.0;
const float minVolts = 1.4;
const float maxVolts = 2.1;
const float referenceVolts = 5.0;
unsigned long currentTime = 0;
unsigned long prevTime = 0;
unsigned long prevVoltTestTime = 0;
U8G2_SH1106_128X64_NONAME_F_4W_HW_SPI u8g2(U8G2_R0, 10, 9, 8); //Duinotech 7 pin 1.3" OLED from Jaycar.
// CS = 10; DC = 9; RES = 8; CLK = 13; MOSI = 11; --- Pins 13 and 11 aren't defined but need to be connected.
//U8G2_SSD1306_128X64_NONAME_1_SW_I2C u8g2(U8G2_R0, /* clock=*/ SCL, /* data=*/ SDA, /* reset=*/ U8X8_PIN_NONE);
//DFR0650 OLED DISPLAY. ON ARDUINO NANO EVERY: SCL = A5; SDA = A4;
const uint8_t tile_area_x_pos = 9; // Update area left position (in tiles. 1 tile = 10 cursor)
const uint8_t tile_area_y_pos = 0; // Update area upper position (distance from top in tiles)
const uint8_t tile_area_width = 5;
const uint8_t tile_area_height = 8; // this will allow cour18 chars to fit into the area
const u8g2_uint_t pixel_area_x_pos = tile_area_x_pos*8;
const u8g2_uint_t pixel_area_y_pos = tile_area_y_pos*8;
const u8g2_uint_t pixel_area_width = tile_area_width*8;
const u8g2_uint_t pixel_area_height = tile_area_height*8;
//------------------------------------//
void setup() {
//Serial.begin(115200);
pinMode(mosfet, OUTPUT);
digitalWrite(mosfet, LOW);
u8g2.begin();
u8g2.enableUTF8Print(); // enable UTF8 support for the Arduino print() function
u8g2.clearBuffer();
u8g2.setFont(u8g2_font_prospero_nbp_tr);
u8g2.setCursor(19, 17);
u8g2.print("Duty Cycle:");
u8g2.setCursor(10, 31);
u8g2.print("Target Amps:");
u8g2.setCursor(27, 45);
u8g2.print("Raw Amps:");
u8g2.setCursor(21, 60);
u8g2.print("Volts/Cell:");
u8g2.sendBuffer();
}
//------------------------------------//
void loop() {
currentTime = millis();
if(currentTime - prevTime >= 300){
updateOLED();
prevTime = currentTime;
}
targetPotVal = analogRead(targetPotPin);
currentVal = analogRead(currentSensePin);
voltageVal = analogRead(voltSensePin);
int filteredTarget = adcFilter1.filter(targetPotVal);
int filteredCurrent = adcFilter2.filter(currentVal);
int filteredVoltage = adcFilter3.filter(voltageVal);
/*-----------------------------------------------------------
initialize current sensor. 0 current will read 2.5v on analog
pin, so this will now write a value between -60 and +60amps
-----------------------------------------------------------*/
current = (2.5 - (filteredCurrent / 1024.0) * referenceVolts) / -0.04;
/*-----------------------------------------------------------
Map target amps to a value between 7.00amps and 10.00amps
-----------------------------------------------------------*/
int val = (filteredTarget * 10);
val = map(val, 0, 10230, 70, 101);
target = val / 10.0;
/*-----------------------------------------------------------
Increase or decrease current to match targetCurrent
-----------------------------------------------------------*/
if(current <= (target - targetBuffer)){
correctedCurrent = current + 0.1;
}
else if(current >= (target + targetBuffer)){
correctedCurrent = current - 0.1;
}
/*-----------------------------------------------------------
Convert correctedCurrent to PWM value and write to mosfet pin
-----------------------------------------------------------*/
dutyCycle = (correctedCurrent / 60.0) * 255.0;
analogWrite(mosfet, dutyCycle);
/*-----------------------------------------------------------
Calculate values for volts and dutycycle for display readout
-----------------------------------------------------------*/
voltage = (filteredVoltage / 1023.0) * referenceVolts;
dutyCyclePercent = (dutyCycle/255.0)*100;
/* if(currentTime - prevVoltTestTime >= 5000){
while(voltage <= minVolts){
analogWrite(mosfet, LOW);
u8g2.clearBuffer();
u8g2.setFont(u8g2_font_prospero_nbp_tr);
u8g2.setCursor(8, 25);
u8g2.print("<--Low Cell Voltage-->");
u8g2.setCursor(11, 50);
u8g2.print("Shutdown Immediately!");
u8g2.sendBuffer();
}
while(voltage >= maxVolts){
analogWrite(mosfet, LOW);
u8g2.clearBuffer();
u8g2.setFont(u8g2_font_prospero_nbp_tr);
u8g2.setCursor(6, 25);
u8g2.print("<--High Cell Voltage-->");
u8g2.setCursor(11, 50);
u8g2.print("Shutdown Immediately!");
u8g2.sendBuffer();
}
while(current >= maxCurrent){
analogWrite(mosfet, LOW);
u8g2.clearBuffer();
u8g2.setFont(u8g2_font_prospero_nbp_tr);
u8g2.setCursor(1, 25);
u8g2.print("Max Amperage Exceeded!");
u8g2.setCursor(11, 50);
u8g2.print("Shutdown Immediately!");
u8g2.sendBuffer();
}
prevVoltTestTime = currentTime;
}*/
}
//-------------------------------------//
void updateOLED(){
u8g2.clearBuffer();
u8g2.setFont(u8g2_font_prospero_nbp_tr);
u8g2.setCursor(85, 17);
u8g2.print(dutyCyclePercent);
u8g2.setCursor(100, 15);
u8g2.print("%");
u8g2.setCursor(85, 31);
u8g2.print(target);
u8g2.setCursor(85, 45);
u8g2.print(current);
u8g2.setCursor(85, 60);
u8g2.print(voltage);
u8g2.setDrawColor(1);
u8g2.updateDisplayArea(tile_area_x_pos, tile_area_y_pos, tile_area_width, tile_area_height);
}