PowerBox: a Solar Panel Charge Management System by Andrea & Nelson

View on GitHub

POWERBOX VIDEO

Introduction

Smart electricity grids have changed the way renewable energy sources power homes across the world. Recent innovations, such as the Tesla Powerwall, have made decentralized renewables generation both more accessible and cost effective for the general public. Inspired by this, we designed a solar panel charge management system that emulates a full-scale home-based renewable power generation system. Our system powers the "home" using solar panels and diverts excess energy for storage in a battery, and also re-routes power from the battery to the "home" when the solar panel is not generating sufficient power.

Our project capitalizes on our knowledge in this class through the use of the following skills:

Bill of Materials

Component Quantity
5V One Channel Relay Module B00LW15A4W 3
I2C 16x2 LCD Display Module 1
Push-button Switch 1
9V DC Step-down Converter 1
9V Battery 1
Photovoltaic 1
14V Rechargeable Battery 1
3V LED 4
FRDM-KL46Z Board 1

Testing our code without these materials:

System Overview

The central challenge of our project is to route power efficiently between the PV, the battery, and the load. To achieve this aim, we used our FRDM-KL46Z board to control various peripheral devices and measure inputs from several sources. Decisions for power routing are made according to a switching algorithm, described in the decision tree below.

We devised a high-level decision tree that outlines the different cases in which we should route power between the circuit components.

Switching Circuitry

We use relays to isolate our low-voltage board circuit from the high voltage battery and solar panel circuit, and implement the above decision tree through switching. The 5V relays are powered using a separate 9V battery stepped down to 5V using a DC step-down converter, instead of being powered by the board. This helps us to reduce the total current drawn from the board during operation to prevent damage from occurring.

Relays are controlled using the KL46Z's GPIO pins PTD2, PTD4, and PTD6.

The exact switching points are dependent on voltage measurements from several points in the circuit. Tracking these measurements allows us to regulate the power flowing into the battery and load at all times. The voltage measurements are obtained from the analog inputs V1 and V2 labeled in the schematic below, using the FRDM-KL46Z ADC pins.

Detailed Technical Description

Switching Algorithm – tomardecision found in core.c

Our switching algorithm performs the decision-making needed to route power throughout our circuit. We have christened it “tomardecision”, which means “to make a decision” in Spanish. Our software implementation of this algorithm consists of:

There are several key features of our solar charging circuit that are managed by individual subsystems, listed below. Acquiring Analog Data – Analog-Digital Conversion with Direct Memory Access Displaying Data – I2C 16x2 LCD Display Routing Power – Digital GPIO relay control As seen above, each of these subsystems utilized a unique capability of the board. The specific implementations of these subsystems are described in detail in the following sections.

Acquiring Analog Voltage Reading – Analog-Digital Conversion with Direct Memory Access

Purpose

Our system reads the voltage at the V1 and V2 nodes, as shown in the schematic above. V1 and V2 track the scaled-down voltage produced by the PV and battery respectively, allowing us to monitor for when the PV voltage exceeds the battery voltage and enable battery recharging.

Implementation of ADC

We implemented single-ended 16-bit Analog-Digital Conversion (ADC) inputs with continuous Direct Memory Access (DMA) transfer to read raw values from pins PTD 20 (ADC0_SE0) and PTD 21 (ADC0_SE4a). DMA transfer was our preferred method of obtaining data, primarily because this allows us to transfer data from the ADC peripheral to memory without the participation of the processor. This enabled us to run our switching process as a single thread, thereby avoiding the need to run a concurrent data transfer process that would slow down management of the high power load circuit.

In our software, we built upon the helper packages provided by the NXP software suite to enable DMA transfer for continuous ADC readings. Our main reference was the NXP ADC16_continuous_dma SDK sample. We created custom ADC channel configurations that correspond to addresses for each of the two single-ended input pins. In our tomardecision() function, which runs every second, we then read from each single-ended input in turn by changing the ADC channel 0 configuration to our custom channel configurations.

Raw readings from these 16-bit ADC inputs allowed us to obtain values of the voltage at each pin. Each ADC reading ranges from 0 (corresponding to 0V) to 2^16 (corresponding to 3.3V) on a linear scale. To obtain the real values of the battery and PV voltages, we first mapped the ADC reading to the 0-3.3V scale, then multiplied it by a conversion factor of 11 arising from our resistive divider circuit.

Testing ADC

During subsystem testing to verify our ADC implementation, we performed the following steps: Display raw ADC data to console using the debug PRINTF() function. ADC data should be displayed and non-zero when the data is being read correctly.

Displaying Data – I2C 16x2 LCD Display

Purpose

We enable our system user to have a quick overview of circuit operating status by displaying a summary of important data on a 16x2 LCD display – the information includes PV and battery terminal voltage levels, switching status, and battery charging status.

Symbols used:

Materials

The 16x2 LCD we used is based on the HD44780 LCD. It operates using the same commands and initialization procedure, which was important in creating our own LCD library for the FRDM board. On its own, the LCD uses serial pins to interface with other hardware. However, we opted to use a combined hardware package where the HD44780-compliant LCD is attached to a PCF8574T I2C chip. The PCF8574T chip converts the incoming I2C signal to the appropriate I/O commands to be interpreted by the LCD display's serial input.

We opted to use I2C due to its capabilities in short-range inter-device communication, as well as the fact that it allows us to economize on the number of the KL46Z's I/O pins used to interface with the LCD. The I2C implementation only uses 2 I/O (SCL & SDA) pins and 2 power terminals (Vdd & GND) which are powered directly by the board from its 5V output pin.

Implementation of I2C LCD Driver

Although there is considerable support for I2C 16x2 LCD displays on many embedded platforms such as the Arduino, there are few, if any, ready-made I2C LCD libraries that work with the KL46Z out of the box. Therefore, we ported over to the FRDM platform the preeminent I2C LCD Arduino driver: LiquidCrystal_I2C. The original LiquidCrystal_I2C driver is written in C++, and leveraged Arduino I2C communication callbacks which could not be directly applied to our implementation in C.

This was why we first set up an I2C library, I2C_Master.h based on the implementation found in this reference. This I2C library leverages the MKL46Z-defined I2C structs and macros to initialize the I2C module and initiate data transfer.

Using the I2C callbacks in I2C_Master.h, we translated the LiquidCrystal_I2C driver into a C-based driver in LCD_Driver.h. The 16x2 LCD is controlled using 8-bit commands that perform tasks ranging from turning on the backlight, setting cursor position, to animating the cursor blinking. One particular quirk we noticed was that although the 16x2 LCD supports 8-bit commands, it was recommended to operate the 16x2 LCD in 4-bit command mode. This meant that the process of transferring the 8-bit commands over I2C involved splitting each command into the higher 4 bits and lower 4 bits and sending them in two separate steps.

Testing

Testing and refining the 16x2 LCD Driver is an iterative process involving three main stages: Create foundational commands which will be used by all other complex commands in the driver library. Verify that these foundational commands by checking if data is successfully transferred over the I2C protocol. This is achieved by observing the LCD for display changes upon writing. Compose more complex and abstract commands, such as writing by lines, using these foundational commands. It was through this process that we realized the importance of splitting the 8-bit commands into 4-bit nibbles to be transferred to the LCD.

Routing Power – Digital GPIO Relay Control

Purpose

With the switching algorithm in place, we use its results to route power between the circuit sections. This involves changing the state of the relays in the circuit using GPIO.

We also track when the load has been switched on. In the schematic above, we connect the B1 input to U3 to a GPIO input pin.

Materials

We use 5V relays in our circuit that are powered by an external 5V power supply. When the IN terminal for a relay is low, the relay connects the NC terminal to COM. Conversely, when the IN terminal for a relay is high, the relay connects the NO terminal to COM.

Implementation

To control an individual relay, we connect a corresponding GPIO output pin on the board to the IN terminal of the relay and adjust the output state for that GPIO pin. We do this by writing to the Port Set Output Register to turn the pin on, and write to the Port Clear Output Registers to turn the pin off. This applies for the relay inputs IN1 and IN2, shown in the schematic above.

B1 is connected to a GPIO input. In order to avoid overloading the 3.3V GPIO pin, B1 is connected to a physical switch that is held at 3.3V by the external DC voltage converter. Thus, the maximum input voltage for U3 IN is 3.3V.

We initially intended to use a Bidirectional Logic Level Shifter to step up the 3.3V GPIO output to 5V at the relay inputs. However, after testing, we realized that 3.3V was sufficient to trigger the change in relay state at the relay IN terminals. Thus, we wired the IN terminals of the relays directly to their corresponding pins on the KL46Z board.

By mimicking the initialization routines used by the C++ library and capitalizing the KL46Z library's I2C capabilities, we were able to successfully initialize and write data to the LCD.

Testing

Testing was a key stage in the development of our project. Every time we included a new feature, we began by implementing and testing the most basic structure or edge case. As the tests succeeded, we included more features and progressively evolved the system’s complexity.

To do this, we followed the concept of test cases that we have practiced throughout the semester: we developed a test case with known results and compared the performance of the code and circuitry to the expected outputs. Moreover, to visualize the values and decisions being made by our algorithm, we used the debug PRINTF() function to indicate which relays were opened, which were closed, and what voltage or ADC values were being read. We connected to the serial debugging console by screening for the output. An example of our debugging output is shown below.

Both our implementation and testing procedures can be separated into individual components which we addressed in the previous technical implementation section - as well as the final overall system.

System-wide Testing

Once we had ensured that all the components delivered the expected results and wired them together, we devised an iterative testing scheme. Our ultimate goal was to ensure that all branches of the decision tree were being implemented correctly. Our original version of the decision tree prior to our testing the following:

Original (deprecated) decision tree

At the outset, our testing stage was run under the full PV and battery operating conditions, without low-voltage verification. We attempted to construct the decision-making algorithm using this experimentation. However, this approach proved risky, as we ended up burning one of our wires and a resistor. This led us to first test under low voltage conditions, and then proceed with high voltage procedures.

For our low voltage procedure we substituted the solar panel and battery with 3.3V and 5V sources, respectively and tested each branch. In this, we determined the advantage of routing the power to the load by default and allowing the user to control the load directly through a pushbutton. Therefore, the main condition was now whether the solar panel was generating enough power or not, and subsequently we decided to restructure our schematic.

The high-voltage procedure enabled us to test the decision-making algorithm with the real voltages. Because our battery remained at a steady range of 12-13V throughout our testing, we used a function generator to simulate the case where the battery was below 11.5V and thus needed charging. Likewise, to simulate the cases where the solar panel did not generate enough power, we covered it or turned it upside down.

Hardware Challenges

Throughout the implementation and testing stages we were faced with unexpected results from our hardware components. As mentioned, initially we aimed to step the 5V signals routed to the GPIO pins down to 3.3V through the logic level shifter. However, mid-way through our development we saw that the output pins of the shifter had been shorted together and had to feed the 5V signal to the GPIO pins directly. Parallely, when we had already succeeded at implementing and testing all branches, the microprocessor in the board began overheating and releasing smoke. We suspect 5V could have been too much for the GPIO pin. Additionally, the circuitry depleted two 9V batteries and blew out an LED, which led to unexpected errors.

Learning Outcomes

Additionally, we learned some hardware development lessons along the way. Some of the errors we encountered and their solutions were the following:

Work Distribution

Our Final Project began the Saturday before Spring break, when we brainstormed about what project we wished to pursue.

From there, both team members conducted research on the implementation and communicated with the professors for guidance. In our meetings we created our materials list and purchased the hardware by the time we submitted the report and webpage, which Nelson drafted. To develop the code, Nelson explored the communication protocols to interface with the LCD displays and the relays, and developed the code for I2C and GPIO pins. Andrea developed code to read ADC input in differential mode and a circuit schematic, and met with Professors El-Ghazaly and Napp to obtain feedback on our implementation. Both met with Professor Napp to confirm the progress, and per his suggestion, worked together to adapt our ADC single ended analog pins in place of differential inputs. From there, we set up our work in Makerspace, where Andrea integrated the code for the components and Nelson wired the relays, LCD display, battery, and board together. Throughout our development, we engaged in pair programming to verify code correctness and mutually check our logic for the decision-making code. Finally, we filmed the video and wrote the sections for the website together.

Additional Resources

Our DMA ADC implementation is based on the NXP ADC16_continuous_dma SDK sample. The appropriate license has been appended to our core.c file, which contains a derivation of the sample implementation.

LiquidCrystal_I2C for Arduino https://www.arduino.cc/reference/en/libraries/liquidcrystal-i2c/

An understanding of solar charging:

Yarbrough, N. (2021, December 14). What does a solar charge controller do? EXPLORIST.life. Retrieved May 19, 2022, from https://www.explorist.life/what-does-a-solar-charge-controller-do/

Solar Charge Controller Circuitry:

Instructables. (2020, July 22). Arduino Solar Charge Controller (version 2.0). Instructables. Retrieved May 19, 2022, from https://www.instructables.com/ARDUINO-SOLAR-CHARGE-CONTROLLER-Version-20/

I2C reference library:

Tontoni, A. (2022, April 11). How to Write an LCD Driver. Medium. Retrieved May 4, 2022 from https://levelup.gitconnected.com/how-to-write-an-lcd-driver-ccee1c89106c.

Appreciation goes to our professors or insight into the circuitry and components needed for the project: Professor Nils Napp Professor Amal El-Ghazaly