Home
JAQForum Ver 20.06
Log In or Join  
Active Topics
Local Time 19:19 28 Mar 2024 Privacy Policy
Jump to

Notice. New forum software under development. It's going to miss a few functions and look a bit ugly for a while, but I'm working on it full time now as the old forum was too unstable. Couple days, all good. If you notice any issues, please contact me.

Forum Index : Electronics : all home built solar system

     Page 1 of 9    
Author Message
poida

Guru

Joined: 02/02/2017
Location: Australia
Posts: 1387
Posted: 01:44am 06 Apr 2021
Copy link to clipboard 
Print this post

OK, I've finally grown up.
No more proprietary equipment used or needed.
Job done.

1 x home built inverter, 3kW, based on the nanoverter controller and Madness's 6kW power board.

(and I have designed a compatible PCB for the 6kW board. Yet to be built and tested to destruction....that could be fun)

2 x home built MPPT charge controllers. These have calibrated thermistors on the battery terminals, to trim the charge voltage exactly as they warm up or cool down.
I saw no need for the inductor temp sensor but I could use a battery temp...

I can rebuild and repair the lot now. Don't even need schematics, it's all
too easy.

No more $2,700 AU inverters that last 2 years but not one month longer.
No more MPPT controllers that if you send a "Reset" command via the MODBUS interface
while the unit is connected to battery and solar, the unit will blow.
No more expensive components that provide zero support such as schematics and
product assembeld/designed to be user repairable.

(In the old days, Tektronix built oscilloscopes that were user repairable
by design and they give excellent repair information including schematics.)

The control of the 2 MPPT and the inverter is done with a Raspberry Pi.
In addition to this, there is another Arduino Nano giving the controller
the DC Load current data, streep power, inverter real power,
and a few digital I/O pins that can drive 20mA at 5V
one which is used to run the pool pump.

The control software when started up, first connects to all USB devices that are plugged into it's 4 ports. There is no requirement for a device to be in a certain USB port. It is automatically determined which device is located on what port.

The control program main loop is:
send "$" to a open USB port.
Get the result. ("i1 ...." means it's inverter #1, "m0 ..." means MPPT unit #0
"d1 ..." means it's the data-I/0 nano)
parse the rest of the response according to what device it is.

every 2 minutes send web requests to a few database servers to insert
a new row of data.
One local at home, one at work and one located in Sydney


Here is the monitor web page now. It looks the same but it's different.
Maybe a bit simpler.



The control program is written in C and uses no special drivers or libraries.
Straight C, compiles without modification under the latest and a 4 year old
version of R-Pi operating systems.

(too bad the forum CODE tags munges the tab stops..)

/*
cc m12.c  -o m12

mysql> describe nudat;
+----------------------+-------------+------+-----+-------------------+-----------------------------+
| Field                | Type        | Null | Key | Default           | Extra                       |
+----------------------+-------------+------+-----+-------------------+-----------------------------+
| id                   | int(11)     | NO   | PRI | NULL              | auto_increment              |
| vin1                 | float       | YES  |     | NULL              |                             |
| vin2                 | float       | YES  |     | NULL              |                             |
| vout1                | float       | YES  |     | NULL              |                             |
| vout2                | float       | YES  |     | NULL              |                             |
| iin1                 | float       | YES  |     | NULL              |                             |
| iin2                 | float       | YES  |     | NULL              |                             |
| hs_temp1             | float       | YES  |     | NULL              |                             |
| hs_temp2             | float       | YES  |     | NULL              |                             |
| bat_temp1            | float       | YES  |     | NULL              |                             |
| bat_temp2            | float       | YES  |     | NULL              |                             |
| total_energy1        | float       | YES  |     | NULL              |                             |
| total_energy2        | float       | YES  |     | NULL              |                             |
| hs_throttle_current1 | float       | YES  |     | NULL              |                             |
| hs_throttle_current2 | float       | YES  |     | NULL              |                             |
| inv_dcv              | float       | YES  |     | NULL              |                             |
| inv_ac_output        | float       | YES  |     | NULL              |                             |
| inv_oen              | smallint(6) | YES  |     | NULL              |                             |
| inv_pinb             | smallint(6) | YES  |     | NULL              |                             |
| inv_hs_temp          | float       | YES  |     | NULL              |                             |
| inv_tor_temp         | float       | YES  |     | NULL              |                             |
| streetpower          | float       | YES  |     | NULL              |                             |
| loadamps             | float       | YES  |     | NULL              |                             |
| target_volts         | float       | YES  |     | NULL              |                             |
| battery_temp         | float       | YES  |     | NULL              |                             |
| ts                   | timestamp   | NO   |     | CURRENT_TIMESTAMP | on update CURRENT_TIMESTAMP |
| ddate                | datetime    | YES  |     | NULL              |                             |
| loadamps_peak        | float       | YES  |     | NULL              |                             |
| realpower            | float       | YES  |     | NULL              |                             |
| inv_stopreason       | smallint(6) | YES  |     | NULL              |                             |
+----------------------+-------------+------+-----+-------------------+-----------------------------+
30 rows in set (0.01 sec)

*/

#include <stdio.h>
#include <string.h>
#include "stdio.h"
#include "stdlib.h"
#include "strings.h"
#include <signal.h>
#include <time.h>

#include <unistd.h>                     //Used for UART
#include <fcntl.h>                      //Used for UART
#include <termios.h>                    //Used for UART


typedef struct
       {
       int usb_fs;
       int dev_type;
       int dev_id;
       } _USB_SP;
_USB_SP usb_sp[4];

typedef struct
       {
       float vin,vout,iin,iout,hs_temp,target_volts;
       float bat_temp,total_energy,hs_throttle_current;
       int id, track_mode,got_data;
       } _MPPT;
_MPPT mppt[3];                          // for id = 1 and id = 2 and id = 0

typedef struct
       {
       float dcv,hs_temp,tor_temp,ac_output,dci;
       int oen,stop_reason,fan_ctl,got_data,pinb;
       } _INV;
_INV inv;

typedef struct
       {
       float a0,a1,a2,a3,max_a0,c0,c1;
       int got_data;
       } _DATALOGGER;
_DATALOGGER dlog;


typedef struct
{
float vin1,vout1,iin1,iout1,hs_temp1, bat_temp1,total_energy1,hs_throttle_current1;
float vin2,vout2,iin2,iout2,hs_temp2, bat_temp2,total_energy2,hs_throttle_current2;
float inv_dcv,inv_ac_output,inv_hs_temp,inv_tor_temp;
int inv_oen, inv_stopreason, inv_pinb;
float realpower,streetpower, loadamps, target_volts, battery_temp,loadamps_peak,inv_cutoff;
} _NUDATA;

_NUDATA nudata;

typedef struct
{
float loadamps;
float invpeakcurrent;
float array2_amps;
float realpower;
float streetpower;
float bv,tv,cc,av,ac,op,svmp,swoc,swpm,bt,hst,chargestate,ledstate, vcutoff, vcutin,tscc,tsbv,tshst,tsbt,tspwm;
int whr;
} _datah;

typedef struct
{
float vcutoff,vcutin;
    int i; // read current switch status  ON=1 OFF=0
float co_v1 ;
float co_a1 ;
float co_v2 ;
float co_a2 ;
    int ioverride;
    int icmd;
    int got_info;
    int c;
} _invctl;


_invctl invctl;
_datah datah;

char dstr[1000];
char tdstr[1000];
time_t rawtime;
struct tm tm;
int d_nano;




void serial_write(char *s,int i)
       {
       int count;
if (i == -1) return;
       if (usb_sp[i].usb_fs != -1)
               {
               count = write(usb_sp[i].usb_fs, s,strlen(s));
               if (count < 0)
                       {
                       printf("UART TX error\n");
                       usb_sp[i].usb_fs = -1;
                       }
               }
       }


void init_usb(int i)
       {
       // for all 4 USB ports, try to open as a file stream
       // dev_type = -1 when not used, = 1 for inverter, = 2 for mppt
       // usb_fs = file descriptor, -1 if not used.
       // with the r-pi, the device names are /dev/ttyUSBx when x = 0 to 3
       //
       char portname[20];
       struct termios options;
               if (usb_sp[i].usb_fs != -1)
                       close(usb_sp[i].usb_fs);
               usb_sp[i].usb_fs = -1;
               usb_sp[i].dev_type = -1;
               //
               // try to open it
               //
               sprintf(portname,"/dev/ttyUSB%1d",i);
               //printf(" trying to open dev %s\n",portname);

               usb_sp[i].usb_fs = open(portname, O_RDWR | O_NOCTTY | O_NDELAY);          //Open in non blocking read/wr$
               if (usb_sp[i].usb_fs == -1)
                       {
                       printf("\nError - Unable to open %s",portname);
                       }
               else
                       {
                       tcgetattr(usb_sp[i].usb_fs, &options);
                       options.c_cflag = B9600 | CS8 | CLOCAL | CREAD;         // baud rate
                       options.c_iflag = IGNPAR | ICRNL;
                       //options.c_cflag |= CRTSCTS; // RTS/CTS Flow Control
                       options.c_oflag = 0;
                       options.c_lflag = 0;
                       tcflush(usb_sp[i].usb_fs, TCIFLUSH);
                       tcsetattr(usb_sp[i].usb_fs, TCSANOW, &options);
                       printf("\n%s opened OK",portname);
                       }
       }



void get_data(int i)
       {
       // determine what type of device, get id, then get data for that device
       char buf[100],*ptr;
       int n,j,dev_type,dev_id;
       n=-1;
j=0;
while((n < 5) && (j++ < 20))
        {
serial_write("$\n\r",i);                // send '$' <cr,lf> to get the running data from a device from the USB tty port
        usleep(500000);
        memset(buf,0,100);
        n = read(usb_sp[i].usb_fs,buf,99);
}
       if (n > 0)
               {
               //printf("\n%s",buf);fflush(stdout);
               if (buf[0] == 'd')
                       {
                       ptr = strtok(buf," "); // go past "d1" datalogger, id=1 by default
                       ptr = strtok(NULL," "); if(ptr != NULL) dlog.a0 = atof(ptr);
                       ptr = strtok(NULL," "); if(ptr != NULL) dlog.a1 = atof(ptr);
                       ptr = strtok(NULL," "); if(ptr != NULL) dlog.a2 = atof(ptr);
                       ptr = strtok(NULL," "); if(ptr != NULL) dlog.a3 = atof(ptr);
                       ptr = strtok(NULL," "); if(ptr != NULL) dlog.c0 = atof(ptr);
                       ptr = strtok(NULL," "); if(ptr != NULL) dlog.c1 = atof(ptr);
                       ptr = strtok(NULL," "); if(ptr != NULL) dlog.max_a0 = atof(ptr);
                       dlog.got_data = 1;
d_nano = i;
                       }
               if (buf[0] == 'i')
                       {
                       ptr = strtok(buf," "); // go past "i1" inverter, id=1 by default
                       ptr = strtok(NULL," "); if(ptr != NULL) inv.oen = atoi(ptr);
                       ptr = strtok(NULL," "); if(ptr != NULL) inv.stop_reason = atoi(ptr);
                       ptr = strtok(NULL," "); if(ptr != NULL) inv.pinb = atoi(ptr);
                       ptr = strtok(NULL," "); if(ptr != NULL) inv.dcv = atof(ptr);
                       ptr = strtok(NULL," "); if(ptr != NULL) inv.ac_output = atof(ptr);
                       ptr = strtok(NULL," "); if(ptr != NULL) inv.tor_temp = atof(ptr);
                       ptr = strtok(NULL," "); if(ptr != NULL) inv.hs_temp = atof(ptr);
                       inv.got_data = 1;
                       }
              if (buf[0] == 'm')
                       {
                       j =  buf[1] - '0';              // permit mmpt id from 0 to 2 inclusive
printf("\nj=%d",j); fflush(stdout);
                       ptr = strtok(buf," "); // go past "m1"
                       ptr = strtok(NULL," "); if(ptr != NULL) mppt[j].track_mode = atoi(ptr);
                       ptr = strtok(NULL," "); if(ptr != NULL) mppt[j].vin = atof(ptr);
                       ptr = strtok(NULL," "); if(ptr != NULL) mppt[j].vout = atof(ptr);
                       ptr = strtok(NULL," "); if(ptr != NULL) mppt[j].iin = atof(ptr);
                       ptr = strtok(NULL," "); if(ptr != NULL) mppt[j].iout = atof(ptr);
                       ptr = strtok(NULL," "); if(ptr != NULL) mppt[j].hs_throttle_current = atof(ptr);
                       ptr = strtok(NULL," "); if(ptr != NULL) mppt[j].hs_temp = atof(ptr);
                       ptr = strtok(NULL," "); if(ptr != NULL) mppt[j].bat_temp = atof(ptr);
                       ptr = strtok(NULL," "); if(ptr != NULL) mppt[j].total_energy = atof(ptr);
                       ptr = strtok(NULL," "); if(ptr != NULL) mppt[j].target_volts = atof(ptr);
mppt[j].got_data = 1;
                       }
               }
       }


void zero_datah()
       {
       datah.tsbv = datah.tscc = datah.tshst = 0.0;
       datah.tsbt = datah.tspwm = datah.tscc = 0.0;
       datah.bv = datah.tv = datah.cc = datah.av = 0.0;
       datah.ac = datah.svmp = datah.swoc = datah.swpm = 0.0;
       datah.bt = datah.hst = 0.0;
       datah.chargestate = 0.0;
       datah.ledstate = 0.0;
       }

void zero_mppt(int i)
{
mppt[i].track_mode=0;
mppt[i].vin=mppt[i].vout=mppt[i].iin=mppt[i].iout=0.0;
mppt[i].hs_temp=mppt[i].bat_temp=mppt[i].target_volts = 0.0;
mppt[i].hs_throttle_current=mppt[i].total_energy=0.0;
}

void massage_data()
{
float bt;
// obtain calibrated values, assign to particular mysql fields..
if (dlog.got_data == 1)
{
// calc current sensor values, streetpower
datah.loadamps = nudata.loadamps = -(float)(dlog.a0 - 507) * 0.281;  // was 0.1176, 0.132, 511 offset
datah.invpeakcurrent = nudata.loadamps_peak = -(float)(dlog.max_a0 - 507) * 0.281;  // was 0.1176, 0.132, 511 offset
datah.realpower = nudata.realpower = dlog.c1 * 30.0;
        datah.streetpower = nudata.streetpower = dlog.c0 * 30.0;
datah.whr = dlog.c0;
}
if (mppt[0].got_data == 1) // mppt id=0 is th eleft hand one, no bat temp
{ // so don't copy into datah.bt
datah.bv = nudata.vout1 = mppt[0].vout;
datah.cc = nudata.iout1 = mppt[0].iout;
datah.hst = nudata.hs_temp1 = mppt[0].hs_temp;
datah.bt = nudata.bat_temp1 = mppt[0].bat_temp;
nudata.total_energy1 = mppt[0].total_energy;
nudata.hs_throttle_current1 = mppt[0].hs_throttle_current;
nudata.vin1 = mppt[0].vin;
nudata.iin1 = mppt[0].iin;
}
if (mppt[1].got_data == 1)
{
datah.tsbv = nudata.vout2 = mppt[1].vout;
datah.tscc = nudata.iout2 = mppt[1].iout;
datah.tshst = nudata.hs_temp2 = mppt[1].hs_temp;
datah.bt = nudata.bat_temp2 = mppt[1].bat_temp;
               nudata.total_energy2 = mppt[1].total_energy;
               nudata.hs_throttle_current2 = mppt[1].hs_throttle_current;
               nudata.vin2 = mppt[1].vin;
               nudata.iin2 = mppt[1].iin;
               nudata.battery_temp = mppt[1].bat_temp;
nudata.target_volts = mppt[1].target_volts;

}
if (inv.got_data == 1)
{
nudata.inv_dcv = inv.dcv;
nudata.inv_ac_output = inv.ac_output;
nudata.inv_hs_temp = inv.hs_temp;
nudata.inv_tor_temp = inv.tor_temp;
nudata.inv_pinb = inv.pinb;
nudata.inv_oen = inv.oen;
nudata.inv_stopreason = inv.stop_reason;
}
}

void make_time_strings()
{
dstr[0] = 0;
    tdstr[0] = 0;
    tm = *localtime(&rawtime);
    sprintf(dstr,"%4d%02d%02d",1900+tm.tm_year,1+tm.tm_mon,tm.tm_mday);
    sprintf(tdstr,"%4d%02d%02d%02d%02d%02d",1900+tm.tm_year,1+tm.tm_mon,tm.tm_mday,tm.tm_hour, tm.tm_min,tm.tm_sec);
}


void insert_rows()
{
make_url_and_insert_row_old("139.180.165.109");
make_url_and_insert_row_old("smtp.bqdesign.com.au");
make_url_and_insert_row_old("localhost");
make_url_and_insert_row("139.180.165.109");
make_url_and_insert_row("smtp.bqdesign.com.au");
make_url_and_insert_row("localhost");
}

void make_url_and_insert_row_old(char *host)
{
char url[1000];
sprintf(url,"wget  -q -T 10 -t 1 -O wget1 \"http://%s/mppt/nu_row.php?bv=%f&tv=%f&ts=%s&cc=%f&av=%f&ac=%f\
&svmp=%f&swoc=%f&swpm=%f&bt=%f&hst=%f&chargestate=%f&ddate=%s&dtime=%s&loadamps=%f&streetpower=%f&loadampspeak=%f&tscc=%f&realpower=%f&meterwhr=%d\""
,host,datah.bv,datah.tv,tdstr,datah.cc,datah.av,datah.ac,datah.svmp,datah.swoc,datah.swpm,datah.bt,datah.hst,
datah.chargestate,dstr,tdstr,datah.loadamps,datah.streetpower,datah.invpeakcurrent,datah.tscc,datah.realpower,datah.whr);
system(url);
}

void make_url_and_insert_row(char *host)
{
char url[1000];
       sprintf(url,"wget  -q -T 10 -t 1 -O wget1 \"http://%s/mppt/nudata_row.php?\
ddate=%s&vin1=%f&vout1=%f&iin1=%f&iout1=%f&hs_temp1=%f&bat_temp1=%f&total_energy1=%f&hs_throttle_current1=%f\
&vin2=%f&vout2=%f&iin2=%f&iout2=%f&hs_temp2=%f&bat_temp2=%f&total_energy2=%f&hs_throttle_current2=%f\
&inv_dcv=%f&inv_ac_output=%f&inv_hs_temp=%f&inv_tor_temp=%f&inv_oen=%d&inv_stopreason=%d&inv_pinb=%d\
&realpower=%f&streetpower=%f&loadamps=%f&target_volts=%f&battery_temp=%f&loadamps_peak=%f&inv_cutoff=%f\""
       ,host,tdstr,nudata.vin1,nudata.vout1,nudata.iin1,nudata.iout1,nudata.hs_temp1,nudata.bat_temp1,nudata.total_energy1,nudata.hs_throttle_current1,
       nudata.vin2,nudata.vout2,nudata.iin2,nudata.iout2,nudata.hs_temp2,nudata.bat_temp2,nudata.total_energy2,nudata.hs_throttle_current2,
nudata.inv_dcv,nudata.inv_ac_output,nudata.inv_hs_temp,nudata.inv_tor_temp,nudata.inv_oen,nudata.inv_stopreason,nudata.inv_pinb,
nudata.realpower,nudata.streetpower,nudata.loadamps,nudata.target_volts,nudata.battery_temp,nudata.loadamps_peak,nudata.inv_cutoff);
       system(url);
}


void get_inv_control()
{
char buf[100];
int j;
FILE *fp;

sprintf(buf,"wget  -q -T 10 -t 1 -O wgetinfo \"http://localhost/mppt/get-dinfo.php\"");
system(buf);
fp = fopen("wgetinfo","r");
       if (fp != NULL) fgets(buf,20,fp); invctl.vcutoff = atof(buf);
       if (fp != NULL) fgets(buf,20,fp); invctl.vcutin = atof(buf);
       if (fp != NULL) fgets(buf,20,fp); invctl.i = atoi(buf);
       if (fp != NULL) fgets(buf,20,fp); invctl.co_v1 = atof(buf);
       if (fp != NULL) fgets(buf,20,fp); invctl.co_a1 = atof(buf);
       if (fp != NULL) fgets(buf,20,fp); invctl.co_v2 = atof(buf);
       if (fp != NULL) fgets(buf,20,fp); invctl.co_a2 = atof(buf);
       if (fp != NULL) fgets(buf,20,fp); invctl.ioverride = atoi(buf);
       if (fp != NULL) fgets(buf,20,fp); invctl.icmd = atoi(buf);
       if (fp != NULL) fgets(buf,20,fp); invctl.c = atoi(buf);
invctl.got_info = 1;

fclose(fp);
printf("\nvcutoff = %f, vcutin = %f i = %d\n",invctl.vcutoff,invctl.vcutin,invctl.i);
printf("v1=%f,a1=%f,v2=%f,a2 = %f\n",invctl.co_v1,invctl.co_a1,invctl.co_v2,invctl.co_a2);
printf("ioverride=%d,icmd = %d, c = %d",invctl.ioverride,invctl.icmd,invctl.c);
printf("\nget inv control() completed\n"); fflush(stdout);
}


void do_inv_control()
{
char buf[1000];
int j;

// parse control word for output pins D6, d7
if ((invctl.c & 0x02) == 0x02)
serial_write("+",d_nano); // HIGH output ..
else
serial_write("-",d_nano); // LOW output please..
serial_write("6",d_nano); // pin D6
if ((invctl.c & 0x01) == 0x01)
    serial_write("+",d_nano);
    else
        serial_write("-",d_nano);
serial_write("5",d_nano); // pin d5

printf(" ioverride = %d",invctl.ioverride); fflush(stdout);
    if (invctl.ioverride == 1)
        {
        printf("\n inverter override in control, set to %d ",invctl.icmd);
invctl.i = invctl.icmd;
        if (invctl.icmd == 1)
printf("\n override: inverter ON"); // switch inverter ON
else
printf("\n override: inverter OFF"); // switch inverter OFF
        }
else
{
printf("\n since ioverride = 0 we are here: ");
// if (bv < vcutoff)
// linear interpolate cut off voltage using inverter current from co_a1 to co_a2
// if current is less than co_a1, clamp it to co_v1
// if more than co_a2, clamp it to co_v2
// ensure v1 > v2 and a1 < a2
//
invctl.vcutoff = invctl.co_v1;
if (datah.loadamps > invctl.co_a1 && datah.loadamps < invctl.co_a2)
invctl.vcutoff = invctl.co_v1 - (invctl.co_v1 - invctl.co_v2)*((datah.loadamps - invctl.co_a1)/(invctl.co_a2 - invctl.co_a1));
if (datah.loadamps > invctl.co_a2)
invctl.vcutoff = invctl.co_v2;
printf("\ncutoff = %f,  battery voltage = %f",invctl.vcutoff,datah.bv);
nudata.inv_cutoff = invctl.vcutoff;
if (datah.bv < invctl.vcutoff)
        {
invctl.i = 0;
printf("\n LV - stop inverter");
      }
        if (datah.bv > invctl.vcutin)
        {
    if (invctl.i == 0)
    printf("\n  restart inverter");
    else
    printf("\n run inverter");
// else it was = 1 already so it's been running
invctl.i = 1;
      }
        }

// write inverter switch status
if(invctl.i == 1)
serial_write("-",d_nano); // nano D7 LOW = inverter ON
else
serial_write("+",d_nano); // D7 HIGH = inverter OFF
serial_write("7",d_nano); // pin D7

sprintf(buf,"wget  -q -T 10 -t 1 -O wget1 \"http://localhost/mppt/dinfo-update.php?istatus=%d&vcutoff=%f\"",invctl.i,invctl.vcutoff);
system(buf);
fflush(stdout);
}


int main()
{
int i;
long sleeptime; // must be signed. must be.
d_nano = -1;

for(i=0; i < 4; i++)
               {
               usb_sp[i].usb_fs = -1;
               printf("\n init ttyUSB%d",i);
               init_usb(i);
               sleep(5);
               }

invctl.got_info = 0; // must be set = 1 for inv control code to run
while(1)
{
rawtime = time(NULL);
make_time_strings();
system("wget  -q -T 10 -t 1 -O wget1 \"https://freedns.afraid.org/dynamic/update.php?R1JiNzJ4UlpCUm9iT1BSSXdwUVM6MTYwNDk5MzA=\"");
dlog.a0=dlog.a1=dlog.a2=dlog.a3=dlog.max_a0=dlog.c0=dlog.c1=0.0;
       zero_mppt(0);
        zero_mppt(1);
        inv.dcv=inv.hs_temp=inv.tor_temp=inv.ac_output=inv.dci = 0.0;
        inv.oen=inv.stop_reason=inv.fan_ctl=inv.pinb=0;
        zero_datah();

for(i=0; i < 4; i++)
get_data(i);
massage_data();
get_inv_control();
do_inv_control();
make_url_and_insert_row();

sleeptime = 120 - (time(NULL) - rawtime);
if (sleeptime < 1)
{
printf("\nNO sleep needed! sleeptime = %ld",sleeptime); fflush(stdout);
}
else
{
printf("\nneed %ld seconds sleep()",sleeptime); fflush(stdout);  
sleep(120 - (time(NULL) - rawtime) );
}
}
}

wronger than a phone book full of wrong phone numbers
 
Warpspeed
Guru

Joined: 09/08/2007
Location: Australia
Posts: 4406
Posted: 02:13am 06 Apr 2021
Copy link to clipboard 
Print this post

Yup,
When you build it yourself, easy to fix, and you know where all the parts came from and can get replacements easily enough if the smoke ever comes out.

Chinese mystery boxes can be very seductive, but if anything ever goes wrong, straight into the wheelie bin is very likely the only thing you can do with it.
Not really an issue if its a $50 item.  But if its a $500 item it can quickly get expensive if several go pop one after the other.
Cheers,  Tony.
 
johnmc
Senior Member

Joined: 21/01/2011
Location: Australia
Posts: 282
Posted: 04:05am 06 Apr 2021
Copy link to clipboard 
Print this post

Well done Poida,    you and others have made it possible for me to
enjoy building my inverters.

The old saying "if you cannot fix it, you do not own it".

cheers john
johnmc
 
poida

Guru

Joined: 02/02/2017
Location: Australia
Posts: 1387
Posted: 07:18am 06 Apr 2021
Copy link to clipboard 
Print this post

And I must say I could not have done it without the help and encouragement of all on this forum.
wronger than a phone book full of wrong phone numbers
 
Haxby

Guru

Joined: 07/07/2008
Location: Australia
Posts: 417
Posted: 10:34am 06 Apr 2021
Copy link to clipboard 
Print this post

Well done! Can you post some pics?
 
Revlac

Guru

Joined: 31/12/2016
Location: Australia
Posts: 960
Posted: 11:18am 06 Apr 2021
Copy link to clipboard 
Print this post

Nice work Poida.

I think that without things breaking we sometimes might not have enough enthusiasm to jump in with the idea to make something better, or make it your own and be satisfied with it.
A lot of us have to go through a few letdowns before we get on top of it, very satisfying getting something working.
I have always been interested to open things up take a look inside to learn how it works.
So many of the projects my farther and I have made with junk and scrounged parts, the inverter build and others have continued along this path.  

I'm sure you will find many more projects to keep you going.
Cheers Aaron
Off The Grid
 
iannez
Newbie

Joined: 05/07/2019
Location: Italy
Posts: 23
Posted: 08:48am 07 Apr 2021
Copy link to clipboard 
Print this post

Wawww

great great job!

super compliments Poida!

great forum  
Cheers, Angelo
 
Murphy's friend

Guru

Joined: 04/10/2019
Location: Australia
Posts: 575
Posted: 10:18am 07 Apr 2021
Copy link to clipboard 
Print this post

  Revlac said  
A lot of us have to go through a few letdowns before we get on top of it, very satisfying getting something working.
I have always been interested to open things up take a look inside to learn how it works.
So many of the projects my farther and I have made with junk and scrounged parts, the inverter build and others have continued along this path.  

I'm sure you will find many more projects to keep you going.



I too can't resist the urge to open things (often brand new ones) to see what makes them tick and if they could be improved.

That actually paid off recently when I noticed an odd rattle inside the just unpacked little mains powered fan heater I bought for my caravan. Turned out the fan blade had come off its shaft, it looks like its held there just magnetically and the courier might  have dropped the parcel.
Anyway, it would have lasted just seconds without a spinning fan blade and possibly caught fire before I could switch it off.

Lesson learned: fan blades can come off accidentally though I never saw  that kind of blade doing it.

Keep the projects coming Poida, your programming skills are something to aspire to but I, at my age, never will reach, unfortunately.
 
rogerdw
Guru

Joined: 22/10/2019
Location: Australia
Posts: 786
Posted: 01:49pm 07 Apr 2021
Copy link to clipboard 
Print this post

  Haxby said  Well done! Can you post some pics?


Seconded by me. Would love to see a heap of pictures of your gear and setup thanks Poida  ...  and congratulations on reaching this stage.

Particularly interested in your final design for your MPPT charge controllers.
Cheers,  Roger
 
BenandAmber
Guru

Joined: 16/02/2019
Location: United States
Posts: 961
Posted: 12:30am 10 Apr 2021
Copy link to clipboard 
Print this post

Poida THE GREAT!!!!
be warned i am good parrot but Dumber than a box of rocks
 
poida

Guru

Joined: 02/02/2017
Location: Australia
Posts: 1387
Posted: 04:31am 10 Apr 2021
Copy link to clipboard 
Print this post

photos

the whole malarkey:



mppt0:



mppt1:





inverter:







the battery 48V 400Ah SLA:



the brains of the operation:



the workbench:


Edited 2021-04-10 14:35 by poida
wronger than a phone book full of wrong phone numbers
 
rogerdw
Guru

Joined: 22/10/2019
Location: Australia
Posts: 786
Posted: 07:00am 10 Apr 2021
Copy link to clipboard 
Print this post

That is awesome Poida, a picture is worth a thousand words  ...  and answers a lot of questions.
Cheers,  Roger
 
Haxby

Guru

Joined: 07/07/2008
Location: Australia
Posts: 417
Posted: 10:18am 10 Apr 2021
Copy link to clipboard 
Print this post

Is that an unmodified 3kw aerosharp with primary windings added on top?
 
poida

Guru

Joined: 02/02/2017
Location: Australia
Posts: 1387
Posted: 12:39pm 10 Apr 2021
Copy link to clipboard 
Print this post

Haxby:
yes.
wronger than a phone book full of wrong phone numbers
 
Haxby

Guru

Joined: 07/07/2008
Location: Australia
Posts: 417
Posted: 08:28pm 10 Apr 2021
Copy link to clipboard 
Print this post

  poida said  Haxby:
yes.


Nice! I was thinking of doing that for the Pre-made Chinese inverter board I bought.
 
poida

Guru

Joined: 02/02/2017
Location: Australia
Posts: 1387
Posted: 12:16am 11 Apr 2021
Copy link to clipboard 
Print this post

I think the combination of the 3kW with external windings is a good
way to go for moderate power builds.
You save a huge amount of time and effort.
The toroid is not 6kW for all day capable.
It's more 1kW all day with peaks to 6kW when starting motors.
My home inverter (seen above) provides for the house.
It supplies the 2.5kW heater in the dishwasher and the pool pump
(1kW) easily.

Here are the other two spare inverters. Both working.

First is the one that powered the house for a year while I built
a Madness powerboard based unit.

It uses 4 x 3 HY4008 FETS, without on-board totem pole gate drives.
(i.e. a board from Aliexpress.)



This means the IR2110 gate drive chips have their output stages exposed to
what I think are damaging voltage transients from EMI and capacitive coupling
of the FET gates. It works fine. But it's not close to how robust
the Mad board/nanoverter combo is.








next is the test victim inverter. It has 4 x 3 HY4008 FETs on a Madness 6kW
totem pole gate drive powerboard, driven by a nanoverter. This time a 2kW toroid is used.
I have had this driving a 2.5kW hot water urn and then started the 1hp compressor.
This is a solid inverter.
But it has weaknesses that have taught me a bit about builds.
e.g. the air flow is poor when I put it face UP and run it. It gets too hot too quickly. But sit it as shown and the ventilation hole is now at the top, taking warm air from the toroid away. It needs 1/2 the time running the fan when upright.











This inverter is used to try things such as one fan for both heatsink and toroid
cooling, a proper current sensor on the AC output, the serial data LCD,
how small a toroid is possible, and detail changes to nanoverter code.
wronger than a phone book full of wrong phone numbers
 
Murphy's friend

Guru

Joined: 04/10/2019
Location: Australia
Posts: 575
Posted: 04:59am 11 Apr 2021
Copy link to clipboard 
Print this post

Poida, what kind of batteries are these on your sideways mounting system?
 
poida

Guru

Joined: 02/02/2017
Location: Australia
Posts: 1387
Posted: 12:51pm 11 Apr 2021
Copy link to clipboard 
Print this post

Narada rex-c 12V 200 Ah
Carbon SLA, supposed to be good for partial state of charge applications.
I like lead acid since it's hard to blow them up and burn the house down.
Lithium on the other hand...

But if I buy another battery it might be Lithium.
Put it in a steel box, 10 meters from the house.
Maybe OK.
wronger than a phone book full of wrong phone numbers
 
oreo
Newbie

Joined: 11/12/2020
Location: Canada
Posts: 39
Posted: 01:13am 12 Apr 2021
Copy link to clipboard 
Print this post

Awesome!  
Looks very nicely built, and it must give you a great feeling of accomplishment.
Greg
 
Murphy's friend

Guru

Joined: 04/10/2019
Location: Australia
Posts: 575
Posted: 08:53am 12 Apr 2021
Copy link to clipboard 
Print this post

  poida said  Narada rex-c 12V 200 Ah
Carbon SLA, supposed to be good for partial state of charge applications.
I like lead acid since it's hard to blow them up and burn the house down.
Lithium on the other hand...

But if I buy another battery it might be Lithium.
Put it in a steel box, 10 meters from the house.
Maybe OK.


Yes, whatever you are happy with. The Lithium type (LYP) I originally bought does supposedly not burn, it has not in the 8 years since I got them but I had two internally shorted cells - and no fire at all - by now.
The new bank is the Lion type EV power sells, so far no problems either.
Batteries are inside my games room/workshop and not yet in a box (future project).

Nice thing about lithium, saw 90+Amps charge current going into the 2 x 200Ah bank today and they can take all I can throw at them. Fully charged around 55V  and I have never seen them below  53V. My house is completely off grid now.
 
     Page 1 of 9    
Print this page
© JAQ Software 2024