Here are the two sides of the sandwhich:
And here is the assembled sandwhich:
I also tried, in vain, to solder a few SMD components by hand. First the DRV8838 motor driver. Itās devilishly tiny and despite proudly soldering tiny wires nothing worked.
With our (expired) solder paste and reflow oven I didnāt get much further either. Iāll wait for our refrigerator to arrive before trying the reflow method again.
I also failed to hand-solder the LUX sensor which was not quite as small but had fragile pads.
I found a note on solarbotics which explained how their 6+V solar panel could be reduced to half the voltage with an exacto knife and a soldering iron here: https://solarbotics.com/product/scc3733/
Most importantly the circuit appears to function. I only have a few revisions to make to the board:
-one of the caps is very close to the traces and needs heat shrink tubing.
-the edge of the radio board next to the MOSFET is too close to the edge and was burned off.
-There was a short between the 1M and the 150K resistors connected to the FB pin of the LTC3105.
-Things are a little tight for the inductor if this SMD component is to be soldered by hand (things are also tight for the other 1206 components next to the IC). Not sure what the plan is for beginners in the workshop hereā¦
-The female headers Iām using arenāt particularly pretty when snipped up and are also too long, making the sandwhich not very compact.
-I need the DRV8838 and the Lux sensor in SOIC or I need solder paste and a fridge.
-Using double sided FR4 is not fun, itās difficult to cut the second side of copper effectively when you canāt set the focus easily. There is plenty of space on the LTC3105 side of the board for a motor driver.
-Could I find a way to organise the jumper pins between the boards into ābanksā so there are just a few rows of pins to solder (instead of individual pins which are prone to brake on this type of board)?
-the through-board antenna works but it is kind of awkward.
-I now have to switch to the RFM69
UPDATE
Iām going to do one more thing before switching to the RFM69, I will make a new board with a motor driver to test the ability to adjust the panel angle.
Here is the plan:
Here is what is already built:
This will involve recutting the LTC3105 circuit but will not require redoing the radio board. This new board will get around the difficulty of doing a double sided board and uses up the unused space on the LTC board. Here is the new LTC3105 circuit which includes the DRV8833 (a motor driver I happen to have which works at 2.7V):
Here is the board (not yet inverted) for cutting:
and here is the circuit diagram in three parts.
The microchip:
The solar harvester:
And the motor driver:
Here is a photo of the final thing cut out:
Here is a photo of me assembling and testing bits at a time:
And here is the RX side of the board freshly cut:
Hereās the board from eagle:
And the schematic:
Hereās the code for the Atmega328 based board to test the USART functionality before soldering the RF module
/*
ATMEGA 328P USART.c
Created: 6/21/2019 10:39:33 AM
Author : FablabDigiscope
USB - FTDI 3.3V:
Rx to Tx
Tx to Rx
Gnd to Gnd
(NO LED ON chip's RX, but the one on TX doesn't seem to interfere)
To view your Serial output in AVR Studio,
1. Click Tools > Data Visualizer
2. Under Configuration>Modules, click External Connection.
3. Double click Serial Port
4. Configure your port. e.g. Set the Baud Rate to 115200
5. Select your COM port
6. Click Connect.
appears to send ASCII from AVR Studio terminal
LED on PC0 blinks when you send a 'j' in serial
*/
#define F_CPU 8000000
#include <avr/io.h>
#include <util/delay.h>
#include <stdlib.h>
#define BAUD 9600 // define baud
#define BAUDRATE ((F_CPU)/(BAUD*16UL)-1) // set baud rate value for UBRR
// function to initialize UART
void uart_init (void)
{
UBRR0H = (BAUDRATE>>8); // shift the register right by 8 bits
UBRR0L = BAUDRATE; // set baud rate
UCSR0B|= (1<<TXEN0)|(1<<RXEN0); // enable receiver and transmitter
UCSR0C|= (1<<UCSZ01)|(1<<UCSZ00); // 8bit data format + asynchronous mode
}
// function to send data
void uart_transmit (unsigned char data)
{
while (!(UCSR0A & (1<<UDRE0))); // wait while register is free
UDR0 = data; // load data in the register
}
unsigned char uart_recieve (void)
{
while(!(UCSR0A) & (1<<RXC0)); // wait while data is being received
return UDR0; // return 8-bit data
}
int main(void)
{
DDRC = 0b00000001;
uart_init();
unsigned char a;
/* Replace with your application code */
while (1)
{
//transmit
// uart_transmit('alpha');
// PORTA = 0b00000001;
// _delay_ms(1000);
// PORTA = 0b00000000;
// _delay_ms(1000);
//recieve
a = uart_recieve();
_delay_ms(100);
if (a == 'j') //corresponds to a 'j' for instance, but not a 'c'
{
PORTC = 0b00000001;
_delay_ms(1000);
PORTC = 0b00000000;
_delay_ms(1000);
PORTC = 0b00000001;
_delay_ms(1000);
PORTC = 0b00000000;
_delay_ms(1000); //some kind of local echo thing makes it repeat?? Or else the register is not being cleared
}
}
}
Testing parts at time, first the microchip with ISP and LED, then adding the radio, then retesting and finishing the rest of the circuit.
Things to change after this version: add a .1uF capacitor between power for the Atmega328 if using same power as the RF.
The connector for the 3.3V USART plug has gaps and a strange pitch, not a standard header.
Generating code with arduino and uploading it with AVR Studio: Compile the code with Arduino, then make a search for the filename with .hex at the end. Copy this to a convenient location. In AVR Studio you will want to flash a .hex from file location, instead of generating it from a C code. Make sure to let Arduino know that you are using a Pro Mini 3.3V at 8MhZ and make sure you program the CLKDIV fuse to not divide the internal clock by 8. I am using a Arduino pin map image to help with the translation from my pins to the arduino software:
Here is a helpful website for wiring and the code: https://learn.sparkfun.com/tutorials/rfm69hcw-hookup-guide/all
Iām using LOW POWER LABSā code for the RF69 here. Make sure to install their two libraries (SPI Flash and RFM69). Here is the code they provide, I have made a tiny modification for the LED pin.
// RFM69HCW Example Sketch
// Send serial input characters from one RFM69 node to another
// Based on RFM69 library sample code by Felix Rusu
// http://LowPowerLab.com/contact
// Modified for RFM69HCW by Mike Grusin, 4/16
// This sketch will show you the basics of using an
// RFM69HCW radio module. SparkFun's part numbers are:
// 915MHz: https://www.sparkfun.com/products/12775
// 434MHz: https://www.sparkfun.com/products/12823
// See the hook-up guide for wiring instructions:
// https://learn.sparkfun.com/tutorials/rfm69hcw-hookup-guide
// Uses the RFM69 library by Felix Rusu, LowPowerLab.com
// Original library: https://www.github.com/lowpowerlab/rfm69
// SparkFun repository: https://github.com/sparkfun/RFM69HCW_Breakout
// Include the RFM69 and SPI libraries:
#include <RFM69.h>
#include <SPI.h>
// Addresses for this node. CHANGE THESE FOR EACH NODE!
#define NETWORKID 0 // Must be the same for all nodes
#define MYNODEID 1 // My node ID
#define TONODEID 2 // Destination node ID
// RFM69 frequency, uncomment the frequency of your module:
//#define FREQUENCY RF69_433MHZ
#define FREQUENCY RF69_915MHZ
// AES encryption (or not):
#define ENCRYPT true // Set to "true" to use encryption
#define ENCRYPTKEY "TOPSECRETPASSWRD" // Use the same 16-byte key on all nodes
// Use ACKnowledge when sending messages (or not):
#define USEACK true // Request ACKs or not
// Packet sent/received indicator LED (optional):
#define LED A0 // LED positive pin
// Create a library object for our RFM69HCW module:
RFM69 radio;
void setup()
{
// Open a serial port so we can send keystrokes to the module:
Serial.begin(9600);
Serial.print("Node ");
Serial.print(MYNODEID,DEC);
Serial.println(" ready");
// Set up the indicator LED (optional):
pinMode(LED,OUTPUT);
digitalWrite(LED,LOW);
// Initialize the RFM69HCW:
radio.initialize(FREQUENCY, MYNODEID, NETWORKID);
radio.setHighPower(); // Always use this for RFM69HCW
// Turn on encryption if desired:
if (ENCRYPT)
radio.encrypt(ENCRYPTKEY);
}
void loop()
{
// Set up a "buffer" for characters that we'll send:
static char sendbuffer[62];
static int sendlength = 0;
// SENDING
// In this section, we'll gather serial characters and
// send them to the other node if we (1) get a carriage return,
// or (2) the buffer is full (61 characters).
// If there is any serial input, add it to the buffer:
if (Serial.available() > 0)
{
char input = Serial.read();
if (input != '\r') // not a carriage return
{
sendbuffer[sendlength] = input;
sendlength++;
}
// If the input is a carriage return, or the buffer is full:
if ((input == '\r') || (sendlength == 61)) // CR or buffer full
{
// Send the packet!
Serial.print("sending to node ");
Serial.print(TONODEID, DEC);
Serial.print(", message [");
for (byte i = 0; i < sendlength; i++)
Serial.print(sendbuffer[i]);
Serial.println("]");
// There are two ways to send packets. If you want
// acknowledgements, use sendWithRetry():
if (USEACK)
{
if (radio.sendWithRetry(TONODEID, sendbuffer, sendlength))
Serial.println("ACK received!");
else
Serial.println("no ACK received");
}
// If you don't need acknowledgements, just use send():
else // don't use ACK
{
radio.send(TONODEID, sendbuffer, sendlength);
}
sendlength = 0; // reset the packet
Blink(LED,10);
}
}
// RECEIVING
// In this section, we'll check with the RFM69HCW to see
// if it has received any packets:
if (radio.receiveDone()) // Got one!
{
// Print out the information:
Serial.print("received from node ");
Serial.print(radio.SENDERID, DEC);
Serial.print(", message [");
// The actual message is contained in the DATA array,
// and is DATALEN bytes in size:
for (byte i = 0; i < radio.DATALEN; i++)
Serial.print((char)radio.DATA[i]);
// RSSI is the "Receive Signal Strength Indicator",
// smaller numbers mean higher power.
Serial.print("], RSSI ");
Serial.println(radio.RSSI);
// Send an ACK if requested.
// (You don't need this code if you're not using ACKs.)
if (radio.ACKRequested())
{
radio.sendACK();
Serial.println("ACK sent");
}
Blink(LED,10);
}
}
void Blink(byte PIN, int DELAY_MS)
// Blink an LED for a given number of ms
{
digitalWrite(PIN,HIGH);
delay(DELAY_MS);
digitalWrite(PIN,LOW);
}
And here is the one I modified for the RX (it doesnāt have serial so it just blinks when it receives something. However the other board can tell us by serial that it received an ACK)
// RFM69HCW Example Sketch
// Send serial input characters from one RFM69 node to another
// Based on RFM69 library sample code by Felix Rusu
// http://LowPowerLab.com/contact
// Modified for RFM69HCW by Mike Grusin, 4/16
// This sketch will show you the basics of using an
// RFM69HCW radio module. SparkFun's part numbers are:
// 915MHz: https://www.sparkfun.com/products/12775
// 434MHz: https://www.sparkfun.com/products/12823
// See the hook-up guide for wiring instructions:
// https://learn.sparkfun.com/tutorials/rfm69hcw-hookup-guide
// Uses the RFM69 library by Felix Rusu, LowPowerLab.com
// Original library: https://www.github.com/lowpowerlab/rfm69
// SparkFun repository: https://github.com/sparkfun/RFM69HCW_Breakout
// Include the RFM69 and SPI libraries:
#include <RFM69.h>
#include <SPI.h>
// Addresses for this node. CHANGE THESE FOR EACH NODE!
#define NETWORKID 0 // Must be the same for all nodes
#define MYNODEID 2 // My node ID
#define TONODEID 1 // Destination node ID
// RFM69 frequency, uncomment the frequency of your module:
//#define FREQUENCY RF69_433MHZ
#define FREQUENCY RF69_915MHZ
// AES encryption (or not):
#define ENCRYPT true // Set to "true" to use encryption
#define ENCRYPTKEY "TOPSECRETPASSWRD" // Use the same 16-byte key on all nodes
// Use ACKnowledge when sending messages (or not):
#define USEACK true // Request ACKs or not
// Packet sent/received indicator LED (optional):
#define LED 14 // LED positive pin
// Create a library object for our RFM69HCW module:
RFM69 radio;
void setup()
{
// Open a serial port so we can send keystrokes to the module:
// Set up the indicator LED (optional):
pinMode(LED,OUTPUT);
pinMode(7,OUTPUT);
digitalWrite(LED,LOW);
// Initialize the RFM69HCW:
radio.initialize(FREQUENCY, MYNODEID, NETWORKID);
radio.setHighPower(); // Always use this for RFM69HCW
// Turn on encryption if desired:
if (ENCRYPT)
radio.encrypt(ENCRYPTKEY);
}
void loop()
{
digitalWrite(7, HIGH); // turn on MOSFET
// RECEIVING
// In this section, we'll check with the RFM69HCW to see
// if it has received any packets:
if (radio.receiveDone()) // Got one!
{
if (radio.ACKRequested())
{
radio.sendACK();
}
Blink(LED,1000);
}
}
void Blink(byte PIN, int DELAY_MS)
// Blink an LED for a given number of ms
{
digitalWrite(PIN,HIGH);
delay(DELAY_MS);
digitalWrite(PIN,LOW);
}
AVR studio troubles
I am having a very strange problem with AVR Studio. It is having difficulty finding the programmer and, more alarming, it is finding that brand new Atmega 328 chips have all their fuses set to high, most problematically the RSTDSBL fuse which essentially bricks the chips unless you have a high voltage programmer (we donāt).
I replaced my 328p on the board and have the same problem (I did this by holding on to the chip with a pair of tweezers and then using a heat gun in a circle around all the pins until the board fell and I was holding the chip. Then I removed the remaining solder with a solder braid.) After this you have to look under a microscope to make sure no solder schrapnel has been sent across the board to cause a short somewhere.
Iām installed AVR Studio on another computer and am checking to see if the same situation exists. I have replaced my programmer as well as tried with a new jumper cable, nothing is making a difference.
Did a search online and it looks like I need a pull up (10K) on CS so that the RF69 doesnāt introduce gibberish while programmingā¦Yep, that looks like it was it! Updated all boards with a pull-up on CS.
Cool, now everything works, even with the LTC3105 powering the transmitterā¦but only when connected to the same power supply! Urg.
Nope, now thatās fixed. I was just not giving the reciever enough juice in terms of mA.
Errata: (0.1uF on power and new header for USART also)
This is the Arduino test code I used to make sure the transmitter could function with the LTC3105 based power with an 8 second watchdog timer, it sends the voltage of the cap (I had to remove the MOSFET meant to make this task less wasteful though) and then goes back to charging.
// RFM69HCW Example Sketch
// Send serial input characters from one RFM69 node to another
// Based on RFM69 library sample code by Felix Rusu
// http://LowPowerLab.com/contact
// Modified for RFM69HCW by Mike Grusin, 4/16
// This sketch will show you the basics of using an
// RFM69HCW radio module. SparkFun's part numbers are:
// 915MHz: https://www.sparkfun.com/products/12775
// 434MHz: https://www.sparkfun.com/products/12823
// See the hook-up guide for wiring instructions:
// https://learn.sparkfun.com/tutorials/rfm69hcw-hookup-guide
// Uses the RFM69 library by Felix Rusu, LowPowerLab.com
// Original library: https://www.github.com/lowpowerlab/rfm69
// SparkFun repository: https://github.com/sparkfun/RFM69HCW_Breakout
// Include the RFM69 and SPI libraries:
#include <avr/wdt.h>
#include <RFM69.h>
#include <SPI.h>
#include <avr/sleep.h>
// Addresses for this node. CHANGE THESE FOR EACH NODE!
#define NETWORKID 0 // Must be the same for all nodes
#define MYNODEID 2 // My node ID
#define TONODEID 1 // Destination node ID
// RFM69 frequency, uncomment the frequency of your module:
//#define FREQUENCY RF69_433MHZ
#define FREQUENCY RF69_915MHZ
// AES encryption (or not):
#define ENCRYPTKEY "TOPSECRETPASSWRD" // Use the same 16-byte key on all nodes
// Use ACKnowledge when sending messages (or not):
#define USEACK true // Request ACKs or not
// Packet sent/received indicator LED (optional):
#define LED 14 // LED positive pin
#define PGOOD 4 // PGOOD
#define VTEST 8 // VTEST MOSFET
// Create a library object for our RFM69HCW module:
int level = 0;
RFM69 radio;
void setup()
{
// Open a serial port so we can send keystrokes to the module:
pinMode(LED,OUTPUT);
digitalWrite(LED,LOW);
pinMode(7,OUTPUT); //mosfet
pinMode(PGOOD, INPUT); // PGOOD
pinMode(A1, INPUT);
pinMode(LED,OUTPUT);
pinMode(VTEST,OUTPUT);
wdt_enable(WDTO_8S);
}
void loop()
{
digitalWrite(VTEST, HIGH); //turn on MOSFET to read voltage
digitalWrite(7, LOW); // turn off MOSFET
level = digitalRead(PGOOD);
if(level == HIGH)
{
digitalWrite(VTEST, HIGH); //turn on MOSFET to read voltage
digitalWrite(7, HIGH); // turn on MOSFET
radio.initialize(FREQUENCY, MYNODEID, NETWORKID);
radio.setHighPower(); // Always use this for RFM69HCW
// Turn on encryption if desired:
radio.encrypt(ENCRYPTKEY);
char Pstr[10];
char Hstr[10];
char buffer[50];
double P = (analogRead(A1)*0.006451); // analog read out of 1023 (based on .975V as highest value), multiply this ratio by 3.33333 to get the actual.
double H = analogRead(A1);
dtostrf(H, 3,3, Hstr);
dtostrf(P, 3,3, Pstr);
static int sendlength = strlen(buffer);
sprintf(buffer, "BAT: P:%sV H:%s", Pstr, Hstr);
radio.sendWithRetry(TONODEID, buffer, sendlength);
Blink(LED,1000);
level = LOW;
sleep();
}
else
{
digitalWrite(7, LOW); // turn off MOSFET
sleep();
}
}
void Blink(byte PIN, int DELAY_MS)
// Blink an LED for a given number of ms
{
digitalWrite(PIN,HIGH);
delay(DELAY_MS);
digitalWrite(PIN,LOW);
}
void sleep(void)
{
set_sleep_mode(SLEEP_MODE_PWR_DOWN); //select PWR DOWN, the most power savings
sleep_enable(); //set SE bit
sei(); // enable global interrupts
sleep_cpu(); //actually sleep
sleep_disable(); //code reaches this point after interrupt
}
The formula for the voltage sensing using a 20K and 10K voltage divider is the following:
((x/1023)*2.2V)*3
I.E. take the analogRead value (which is out of 1023) and multiply it by the maximum 2.2V that could be sensed to get the voltage after the 20K. This is one third of Vcap, so multiply by three to get Vcap. (We need a voltage divider because the microchip is using LDO at 2.2V while the Vout of the RF is getting Vout at 3.3V)