Fab15 part III

Finally have something that works and is easy enough to assemble and work with.Here is the radio side:

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:

https://www.google.com/url?sa=i&source=images&cd=&ved=2ahUKEwjDtpCx8vriAhVNyxoKHSQLBpEQjRx6BAgBEAU&url=https%3A%2F%2Flearn.sparkfun.com%2Ftutorials%2Fusing-the-arduino-pro-mini-33v%2Fall&psig=AOvVaw2h4IYqUccgSOhJAcis_Tzq&ust=1561217456527846

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)