// QuickCharge 3.0 demo
// Use the library from https://github.com/vdeconinck/QC3Control/blob/master/src/QC3Control.cpp
// to control a Quick Charge power controller
// Copied the QC3Control.h and QC3Control.cpp to this Wokwi
//
// Should control QuickCharge/FastCharge power block
// https://en.wikipedia.org/wiki/Quick_Charge
// See https://forum.arduino.cc/t/hacking-qualcomm-quick-charge-3-0/906880/11
// for a prototype
// The resistors aren't electronically simulated in Wokwi, but per the library's
// diagram, they form voltage dividers to control the D+ and D- voltages on
// a QC2/QC3 charger's data lines. This is simulated here with wokwiSim().
//
// DaveX 2022-03-06 CC BY-SA
// See https://forum.arduino.cc/t/quickcharge-3-0-as-adjustable-voltage-source/966276
// for discussion
const bool inWokwi = true;
#include "QC3Control.h" // quotes for local files in Wokwi
//
// External Connections:
// A0 to D- on QC3
// A1 to D+ on QC3
// Vin is simulating Vbus on the QC3. In real life, disconnect this.
//
//Pin 4 for Data+ 470R to VCC+10K+1K5+GND
//Pin 5 for Data- 470R to VCC+10K+1K5+GND
//See How to connect in the documentation for more details.
QC3Control quickCharge(4, 5);
float Vcc = 5;
float Vbus = 0;
float simVbus = 0;
int simA0, simA1, simA2;
void wokwiSim(void){
// Simulate the the QC3 device and voltage dividers on WokWi
const float r10kP470 = 1/(1.0/10000+1.0/470); // 10K || 470
const float r1k5P470 = 1/(1.0/1500+1.0/470); // 1K5 || 470
simVbus = constrain(quickCharge.getMilliVoltage(),3900,12600)/1000.0;
simA0 = 1024.0*(digitalRead(5) ? (1500/(r10kP470+1500)) : (r1k5P470/(r1k5P470+10000)) );
simA1 = 1024.0*(digitalRead(4) ? (1500/(r10kP470+1500)) : (r1k5P470/(r1k5P470+10000)) );
simA2 = 1024.0*simVbus*10000/(10000.0+47000)/Vcc;
}
void printMVolts() {
int rA0 = analogRead(A0);
int rA1 = analogRead(A1);
int rA2 = analogRead(A2);
if(inWokwi){ // override the analogRead on WokWi with simulated values
wokwiSim();
rA0 = simA0;
rA1 = simA1;
rA2 = simA2;
}
Vcc = readVcc() / 1000.0;
Serial.print(quickCharge.getMilliVoltage());
Serial.print("mV, D-: ");
Serial.print((rA0 + 0.5) * Vcc / 1024);
Serial.print("V, D+: ");
Serial.print((rA1 + 0.5) * Vcc / 1024);
Serial.print("V, VBus: ");
Serial.print(Vbus = (rA2 + 0.5) / 1024.0 * Vcc * (46.29 + 9.89) / 9.89 ); //
Serial.print("V, Vcc=");
Serial.print(Vcc); //
Serial.println("V ");
}
long readVcc() {
// https://forum.arduino.cc/t/how-to-know-vcc-voltage-in-arduino/344001/3
long result;
byte ADMUXsave = ADMUX;
// 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;
ADMUX = ADMUXsave;
result = 1126400L / result; // Back-calculate AVcc in mV
//Serial.println(result);
return result;
}
void setup() {
Vcc = readVcc() / 1000.0;
quickCharge.begin();
Serial.begin(115200);
//set voltage to 12V
quickCharge.set5V();
//delay(5000);
//quickCharge.set12V();
Serial.print("QuickChargeControl.ino -- Control a QuickCharge3\n"
"3.9-12V variable power supply with an Arduino.\n"
"Setup: ");
printMVolts();
delay(5000);
}
void demoModes(void) {
const int interval = 1000;
static unsigned long last = 0;
static int mode = 0;
static int ii = 0;
unsigned long now = millis();
if (now - last > interval) {
if (now - last > 4 * interval) {
last = now ;
}
else {
last += interval;
}
Serial.print("Mode ");
Serial.print(mode);
Serial.print(": ");
printMVolts();
switch (mode) {
case 0:
quickCharge.set5V();
mode++;
break;
case 1:
quickCharge.set9V();
mode++;
break;
case 2:
quickCharge.set12V();
mode++;
break;
case 3:
quickCharge.setMilliVoltage(3200);
mode++;
break;
case 4:
quickCharge.setMilliVoltage(12000);
mode++;
break;
case 5: // decrementing 0.2v/step
if (ii < 50) {
ii++;
quickCharge.decrementVoltage();
}
else
{
mode++;
//ii = 60; //override
}
break;
case 6:
if (ii > 0) {
ii--;
quickCharge.incrementVoltage();
}
else
{
mode++;
}
break;
case 7:
quickCharge.set5V();
mode = 0;
break;
default:
mode = 0;
break;
}
}
}
// loopCounter from https://forum.arduino.cc/t/while-loop-as-a-condition-for-limit-switches/963899/11
void LoopCounter() // tells the average response speed of void loop()
{ // inside a function, static variables keep their value from run to run
const unsigned long microsInOneSecond = 1000000UL;
static unsigned long count, countStartMicros; // only this function sees these
count++; // adds 1 to count after any use in an expression, here it just adds 1.
if ( micros() - countStartMicros >= microsInOneSecond ) // 1 second
{
countStartMicros += microsInOneSecond; // for a regular second
Serial.println( count ); // 32-bit binary into decimal text = many micros
count = 0; // don't forget to reset the counter
}
}
void loop() {
//And you can change it on the fly
demoModes();
//LoopCounter();
}