QI wireless charger / tester for a Li-Ion battery
LiPo battery "test & charge". A useful COMPONENT to insert in any of your miniaturized projects.
Devices & Components
Arduino Uno Rev3
QI wireless 5W Coil Circuit Board Module
Through Hole Resistor, 680 kohm
OLED I2C SSD1306 0.96 pollici Display 128 x 64 Pixel (AZDelivery)
Li-Ion 3.7V 250mAh battery
Through Hole Resistor, 220 kohm
Microcontroller PRO Mini w/Atmel AVR ATMEGA328P, 3.3V 8MHz
FT232RL USB to serial TTL (3.3V - 5V) (AZDelivery)
TP4056 Micro USB 5V 1A Li - Ion Battery Charger Module (AZDelivery)
Hardware & Tools
Solder Wire, Lead Free
Soldering iron (generic)
Solder Paste, Tack Flux
Software & Tools
Arduino IDE
Project description
Code
TEST Sketch on Arduino UNO
c_cpp
Breadboard and Arduino UNO test
1// Charger Wireless QI "snippet" by F.Stella 20220314 2 3#include <SPI.h> 4#include <Wire.h> 5#include <Adafruit_GFX.h> 6#include <Adafruit_SSD1306.h> 7#include <Fonts/FreeMono9pt7b.h> 8#include <Fonts/FreeMonoBold9pt7b.h> 9#include <Fonts/FreeMonoBold18pt7b.h> 10// #include <Fonts/FreeMonoBold24pt7b.h> 11 12#define SCREEN_WIDTH 128 // OLED display width, in pixels 13#define SCREEN_HEIGHT 64 // OLED display height, in pixels 14 15#define debug0 //attiva stampa DEBUG base e SERIAL 16#define debug1 //attiva stampa DEBUG sezione1 17 18// Declaration for an SSD1306 display connected to I2C (SDA, SCL pins) 19#define OLED_RESET 4 // Reset pin # (or -1 if sharing Arduino reset pin) 20Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET); 21 22 23// 'BatteryLevels_bitmap_12x22', 22x12px 24const unsigned char BatteryLevelFULL [] PROGMEM = { 25 0x1f, 0xff, 0xfc, 0x1f, 0xff, 0xfc, 0x18, 0x00, 0x0c, 0xfb, 0xff, 0xec, 0xfb, 0xff, 0xec, 0xfb, 26 0xff, 0xec, 0xfb, 0xff, 0xec, 0xfb, 0xff, 0xec, 0xfb, 0xff, 0xec, 0x18, 0x00, 0x0c, 0x1f, 0xff, 27 0xfc, 0x1f, 0xff, 0xfc 28}; 29 30const unsigned char BatteryLevelMID [] PROGMEM = { 31 0x1f, 0xff, 0xfc, 0x1f, 0xff, 0xfc, 0x18, 0x00, 0x0c, 0xf8, 0x3f, 0xec, 0xf8, 0x3f, 0xec, 0xf8, 32 0x3f, 0xec, 0xf8, 0x3f, 0xec, 0xf8, 0x3f, 0xec, 0xf8, 0x3f, 0xec, 0x18, 0x00, 0x0c, 0x1f, 0xff, 33 0xfc, 0x1f, 0xff, 0xfc 34}; 35 36const unsigned char BatteryLevelEMPTY [] PROGMEM = { 37 0x1f, 0xff, 0xfc, 0x1f, 0xff, 0xfc, 0x18, 0x00, 0x0c, 0xf8, 0x00, 0xcc, 0xf8, 0x00, 0xcc, 0xf8, 38 0x00, 0xcc, 0xf8, 0x00, 0xcc, 0xf8, 0x00, 0x0c, 0xf8, 0x00, 0xcc, 0x18, 0x00, 0x0c, 0x1f, 0xff, 39 0xfc, 0x1f, 0xff, 0xfc 40}; 41 42byte pin_A = 2; 43byte button_A = 0; 44 45int offset18_x = -2; 46int offset18_y = 22; 47int offset12_x = -2; 48int offset12_y = 14; 49int offset9_x = -1; 50int offset9_y = 12; 51 52unsigned long button_delay_t = 0; 53 54int analoginput = 0; // Battery CHECK analog pin 55int analogamount = 0; // stores incoming value 56float percAREF = 0; 57float percBatt = 0; // used to store our BATTERY percentage charge value 58float voltBatt = 0; 59float voltage = 0; // used to store voltage value 60float V_out = 0; 61float V_source = 0; 62float referenceVoltage = 0; 63int voltageError = 0; 64// float resist1 = 4604; // 4604 tester value 4.7 kOhm nominal - TEST on ARDUINOuno 5V 65// float resist2 = 1000; // 1 kOhm nominal - TEST on ARDUINOuno 5V 66float resist1 = 982000; // 1 MOhm 680 kOhm nominal 67float resist2 = 306000; // 300 kOhm 220 kOhm nominal 68 69void setup() { 70 71#ifdef debug0 72 Serial.begin(19200); 73 Serial.println(F("")); 74 Serial.print(F("Serial START - press button!")); 75 Serial.println(F("")); 76#endif 77 78 analogReference(INTERNAL); // use INTERNAL (1.1V) for reference voltage 79 80 display.begin(SSD1306_SWITCHCAPVCC, 0x3C); 81 display.clearDisplay(); 82 display.setTextColor(WHITE); 83 display.setFont(&FreeMono9pt7b); // PLAIN font 84 85 display.setCursor(1, 10); 86 display.print("Display on."); 87 display.setCursor(25, 30); 88 display.print("press"); 89 display.setCursor(15, 50); 90 display.print("to test"); 91 display.display(); 92 93 pinMode(pin_A, INPUT_PULLUP); //button 94} 95 96void loop() { 97 do { 98 button_A = digitalRead(pin_A); 99 } while ((button_A == 1) || ((millis()-button_delay_t) < 500)); 100 101 button_delay_t = millis(); 102 103 #ifdef debug1 104 Serial.print(F("Button A (")); 105 Serial.print(pin_A); 106 Serial.print(F(") = ")); 107 Serial.println(button_A); 108 #endif 109 batteryCheck(); 110 showSCREEN(); 111} 112 113void showSCREEN() { 114 display.clearDisplay(); 115 display.setTextColor(WHITE); 116 display.setCursor(10+offset18_x, 20+offset18_y); 117 display.setFont(&FreeMonoBold18pt7b); // PLAIN font 118 display.print(voltBatt,1); 119 display.setCursor(85+offset18_x, 20+offset18_y); 120 display.print("V"); 121 122 // display footer *** 123 display.setCursor(47+offset9_x, 51+offset9_y); 124 display.setFont(&FreeMono9pt7b); // PLAIN font 125 display.print(percBatt,1); 126 display.print("%"); 127 128 if (percBatt > 76 ) { // Battery level graphic display 129 display.drawBitmap(0, 53, BatteryLevelFULL, 22, 12, WHITE); 130 } else if (percBatt > 65 ) { 131 display.drawBitmap(0, 53, BatteryLevelMID, 22, 12, WHITE); 132 } else { 133 display.drawBitmap(0, 53, BatteryLevelEMPTY, 22, 12, WHITE); 134 } 135 display.display(); //Send buffer to display 136 delay(3000); 137 138} 139 140void batteryCheck() { 141 referenceVoltage = 1100; // 1100 internal; 142 V_source = 4.2; // LiPo Vmax 4.2V - UNO R3 5.056 - Vs from the divider calculation 143 // using the REAL resistor values makes it more "precise" - one can also set a fixed value 144 V_out = V_source*(resist2)/((resist1)+(resist2)); // UNO 0.889 - LiPo 1.05 - VOut from the divider calculation 145 voltageError = 0; // to empirically adjust ;-) 146 147 analogamount = analogRead(analoginput); 148 percAREF=(analogamount/1024.00)*100; 149 150 voltage=(analogamount/1024.00)*referenceVoltage+voltageError; // in millivolts 151 voltBatt=(voltage*((resist1)+(resist2))/(resist2))/1000; // V_s = V_out * (R1+R2) / R2 152 percBatt=(voltBatt/V_source)*100; 153 154 #ifdef debug1 155 Serial.print("V_out: "); 156 Serial.println(V_out,3); 157 Serial.print("Lettura analog (0-1023): "); 158 Serial.print(analogamount); 159 Serial.print(" -------- % of AREF: "); 160 Serial.print(percAREF,2); 161 Serial.print(" -------- A0 (mV): "); // compare with result of Voltage Divider calculation Vout 162 // for 5.056 (that I checked on Arduino1) and resistors 1K 4.7K is 0.889 163 Serial.print(voltage,2); 164 165 Serial.print(" -------- % of battery nominal: "); 166 Serial.print(percBatt,2); 167 Serial.print(" -------- Real - no divider (V): "); // if you check Arduino voltage should be 5.0x 168 Serial.println(voltBatt,2); 169 Serial.println(""); 170 #endif 171} 172
TEST Sketch on Arduino UNO
c_cpp
Breadboard and Arduino UNO test
1// Charger Wireless QI "snippet" by F.Stella 20220314 2 3#include 4 <SPI.h> 5#include <Wire.h> 6#include <Adafruit_GFX.h> 7#include <Adafruit_SSD1306.h> 8#include 9 <Fonts/FreeMono9pt7b.h> 10#include <Fonts/FreeMonoBold9pt7b.h> 11#include <Fonts/FreeMonoBold18pt7b.h> 12// 13 #include <Fonts/FreeMonoBold24pt7b.h> 14 15#define SCREEN_WIDTH 128 // OLED 16 display width, in pixels 17#define SCREEN_HEIGHT 64 // OLED display height, in 18 pixels 19 20#define debug0 //attiva stampa DEBUG base e SERIAL 21#define 22 debug1 //attiva stampa DEBUG sezione1 23 24// Declaration for an SSD1306 25 display connected to I2C (SDA, SCL pins) 26#define OLED_RESET 4 // Reset pin 27 # (or -1 if sharing Arduino reset pin) 28Adafruit_SSD1306 display(SCREEN_WIDTH, 29 SCREEN_HEIGHT, &Wire, OLED_RESET); 30 31 32// 'BatteryLevels_bitmap_12x22', 22x12px 33const 34 unsigned char BatteryLevelFULL [] PROGMEM = { 35 0x1f, 0xff, 0xfc, 0x1f, 0xff, 36 0xfc, 0x18, 0x00, 0x0c, 0xfb, 0xff, 0xec, 0xfb, 0xff, 0xec, 0xfb, 37 0xff, 0xec, 38 0xfb, 0xff, 0xec, 0xfb, 0xff, 0xec, 0xfb, 0xff, 0xec, 0x18, 0x00, 0x0c, 0x1f, 0xff, 39 40 0xfc, 0x1f, 0xff, 0xfc 41}; 42 43const unsigned char BatteryLevelMID [] 44 PROGMEM = { 45 0x1f, 0xff, 0xfc, 0x1f, 0xff, 0xfc, 0x18, 0x00, 0x0c, 0xf8, 0x3f, 46 0xec, 0xf8, 0x3f, 0xec, 0xf8, 47 0x3f, 0xec, 0xf8, 0x3f, 0xec, 0xf8, 0x3f, 0xec, 48 0xf8, 0x3f, 0xec, 0x18, 0x00, 0x0c, 0x1f, 0xff, 49 0xfc, 0x1f, 0xff, 0xfc 50}; 51 52const 53 unsigned char BatteryLevelEMPTY [] PROGMEM = { 54 0x1f, 0xff, 0xfc, 0x1f, 0xff, 55 0xfc, 0x18, 0x00, 0x0c, 0xf8, 0x00, 0xcc, 0xf8, 0x00, 0xcc, 0xf8, 56 0x00, 0xcc, 57 0xf8, 0x00, 0xcc, 0xf8, 0x00, 0x0c, 0xf8, 0x00, 0xcc, 0x18, 0x00, 0x0c, 0x1f, 0xff, 58 59 0xfc, 0x1f, 0xff, 0xfc 60}; 61 62byte pin_A = 2; 63byte button_A = 64 0; 65 66int offset18_x = -2; 67int offset18_y = 22; 68int offset12_x = -2; 69int 70 offset12_y = 14; 71int offset9_x = -1; 72int offset9_y = 12; 73 74unsigned 75 long button_delay_t = 0; 76 77int analoginput = 0; // Battery CHECK 78 analog pin 79int analogamount = 0; // stores incoming value 80float 81 percAREF = 0; 82float percBatt = 0; // used to store our BATTERY percentage 83 charge value 84float voltBatt = 0; 85float voltage = 0; // 86 used to store voltage value 87float V_out = 0; 88float V_source = 0; 89float 90 referenceVoltage = 0; 91int voltageError = 0; 92// float resist1 = 4604; // 93 4604 tester value 4.7 kOhm nominal - TEST on ARDUINOuno 5V 94// float resist2 = 95 1000; // 1 kOhm nominal - TEST on ARDUINOuno 5V 96float 97 resist1 = 982000; // 1 MOhm 680 kOhm nominal 98float resist2 = 306000; 99 // 300 kOhm 220 kOhm nominal 100 101void setup() { 102 103#ifdef debug0 104 105 Serial.begin(19200); 106 Serial.println(F("")); 107 Serial.print(F("Serial 108 START - press button!")); 109 Serial.println(F("")); 110#endif 111 112 analogReference(INTERNAL); 113 // use INTERNAL (1.1V) for reference voltage 114 115 display.begin(SSD1306_SWITCHCAPVCC, 116 0x3C); 117 display.clearDisplay(); 118 display.setTextColor(WHITE); 119 display.setFont(&FreeMono9pt7b); 120 // PLAIN font 121 122 display.setCursor(1, 10); 123 display.print("Display 124 on."); 125 display.setCursor(25, 30); 126 display.print("press"); 127 display.setCursor(15, 128 50); 129 display.print("to test"); 130 display.display(); 131 132 pinMode(pin_A, 133 INPUT_PULLUP); //button 134} 135 136void loop() { 137 do { 138 button_A 139 = digitalRead(pin_A); 140 } while ((button_A == 1) || ((millis()-button_delay_t) 141 < 500)); 142 143 button_delay_t = millis(); 144 145 #ifdef debug1 146 Serial.print(F("Button 147 A (")); 148 Serial.print(pin_A); 149 Serial.print(F(") = ")); 150 Serial.println(button_A); 151 152 #endif 153 batteryCheck(); 154 showSCREEN(); 155} 156 157void showSCREEN() 158 { 159 display.clearDisplay(); 160 display.setTextColor(WHITE); 161 display.setCursor(10+offset18_x, 162 20+offset18_y); 163 display.setFont(&FreeMonoBold18pt7b); // 164 PLAIN font 165 display.print(voltBatt,1); 166 display.setCursor(85+offset18_x, 167 20+offset18_y); 168 display.print("V"); 169 170 // display footer *** 171 display.setCursor(47+offset9_x, 172 51+offset9_y); 173 display.setFont(&FreeMono9pt7b); // PLAIN 174 font 175 display.print(percBatt,1); 176 display.print("%"); 177 178 if (percBatt 179 > 76 ) { // Battery level graphic display 180 display.drawBitmap(0, 181 53, BatteryLevelFULL, 22, 12, WHITE); 182 } else if (percBatt > 65 ) { 183 display.drawBitmap(0, 184 53, BatteryLevelMID, 22, 12, WHITE); 185 } else { 186 display.drawBitmap(0, 187 53, BatteryLevelEMPTY, 22, 12, WHITE); 188 } 189 display.display(); //Send 190 buffer to display 191 delay(3000); 192 193} 194 195void batteryCheck() { 196 referenceVoltage 197 = 1100; // 1100 internal; 198 V_source = 4.2; // LiPo Vmax 4.2V - 199 UNO R3 5.056 - Vs from the divider calculation 200 // using the REAL resistor values 201 makes it more "precise" - one can also set a fixed value 202 V_out = V_source*(resist2)/((resist1)+(resist2)); 203 // UNO 0.889 - LiPo 1.05 - VOut from the divider calculation 204 205 voltageError = 0; // to empirically adjust ;-) 206 207 analogamount 208 = analogRead(analoginput); 209 percAREF=(analogamount/1024.00)*100; 210 211 voltage=(analogamount/1024.00)*referenceVoltage+voltageError; 212 // in millivolts 213 voltBatt=(voltage*((resist1)+(resist2))/(resist2))/1000; 214 // V_s = V_out * (R1+R2) / R2 215 percBatt=(voltBatt/V_source)*100; 216 217 218 #ifdef debug1 219 Serial.print("V_out: "); 220 Serial.println(V_out,3); 221 222 Serial.print("Lettura analog (0-1023): "); 223 Serial.print(analogamount); 224 225 Serial.print(" -------- % of AREF: "); 226 Serial.print(percAREF,2); 227 228 Serial.print(" -------- A0 (mV): "); // compare with result of Voltage 229 Divider calculation Vout 230 // for 5.056 (that I checked on Arduino1) and resistors 231 1K 4.7K is 0.889 232 Serial.print(voltage,2); 233 234 Serial.print(" -------- 235 % of battery nominal: "); 236 Serial.print(percBatt,2); 237 Serial.print(" 238 -------- Real - no divider (V): "); // if you check Arduino voltage should 239 be 5.0x 240 Serial.println(voltBatt,2); 241 Serial.println(""); 242 #endif 243} 244
Downloadable files
TEST battery and display charge - breadboard sketch
This is a version of the "voltmeter" that uses an Arduino UNO and a simple bradboard set-up..
TEST battery and display charge - breadboard sketch
TEST battery and display charge - breadboard sketch
This is a version of the "voltmeter" that uses an Arduino UNO and a simple bradboard set-up..
TEST battery and display charge - breadboard sketch
Testing + Charging Li-Ion battery with a QI wireless receiver
This is the circuit as I use it in my projects
Testing + Charging Li-Ion battery with a QI wireless receiver
Comments
Only logged in users can leave comments