Author Topic: MODBUS and Raspberry Pi for Off-grid Storage Monitoring (SS-MPPT-15L)  (Read 4921 times)

0 Members and 1 Guest are viewing this topic.

DamonHD

  • Administrator
  • Super Hero Member Plus
  • *****
  • Posts: 4125
  • Country: gb
    • Earth Notes
Hi,

I thought that I would start a thread here about this, though it also sort of extends this earlier thread:

http://www.fieldlines.com/index.php?topic=147639.0

This is the page I shall maintain on my site:

http://www.earth.org.uk/MODBUS-and-Raspberry-Pi.html

Rgds

Damon
Podcast: https://www.earth.org.uk/SECTION_podcast.html

@DamonHD@mastodon.social

Bruce S

  • Administrator
  • Super Hero Member Plus
  • *****
  • Posts: 5370
  • Country: us
  • USA
Re: MODBUS and Raspberry Pi for Off-grid Storage Monitoring (SS-MPPT-15L)
« Reply #1 on: August 10, 2016, 04:22:00 PM »
DamonHD;
Question?
Are you using mixed chemistry batteries?
I'm asking mostly because with working with mixed chemistry batteries there are measurable differences with internal resistances.
SOooo if you're still working with mixed batteries you might take a look at internal resistances versus SoC for the different types you might have.

Bruce S
A kind word often goes unsaid BUT never goes unheard

DamonHD

  • Administrator
  • Super Hero Member Plus
  • *****
  • Posts: 4125
  • Country: gb
    • Earth Notes
Re: MODBUS and Raspberry Pi for Off-grid Storage Monitoring (SS-MPPT-15L)
« Reply #2 on: August 11, 2016, 03:24:49 AM »
All gel lead-acid for now.

Rgds

Damon
Podcast: https://www.earth.org.uk/SECTION_podcast.html

@DamonHD@mastodon.social

DamonHD

  • Administrator
  • Super Hero Member Plus
  • *****
  • Posts: 4125
  • Country: gb
    • Earth Notes
Re: MODBUS and Raspberry Pi for Off-grid Storage Monitoring (SS-MPPT-15L)
« Reply #3 on: August 12, 2016, 02:49:46 PM »
Woot!

USB/serial cable arrived this morning and first tested access to the SS-MPPT-15L from Morningstar's MS VIEW.  Other than their GUI being odd, it AllJustWorked(TM)!

Now I have plumbed the USB into mi Raspberry Pi, and as the first stage wrote a simple program just to access the SS-MPPT-15L and print a key value (actual battery voltage, smoothed).

http://www.earth.org.uk/RPi201406/code/ssmppt15l-modbus.cpp

That code is now making its way into my main power management code.

Rgds

Damon
Podcast: https://www.earth.org.uk/SECTION_podcast.html

@DamonHD@mastodon.social

Bruce S

  • Administrator
  • Super Hero Member Plus
  • *****
  • Posts: 5370
  • Country: us
  • USA
Re: MODBUS and Raspberry Pi for Off-grid Storage Monitoring (SS-MPPT-15L)
« Reply #4 on: August 12, 2016, 03:27:48 PM »
DamonHD;
When I try to open the link, it gives me the dreaded 403 forbidden error message.

Bruce S
A kind word often goes unsaid BUT never goes unheard

DamonHD

  • Administrator
  • Super Hero Member Plus
  • *****
  • Posts: 4125
  • Country: gb
    • Earth Notes
Re: MODBUS and Raspberry Pi for Off-grid Storage Monitoring (SS-MPPT-15L)
« Reply #5 on: August 12, 2016, 04:27:14 PM »
Please try again, I have been actively editing it.

I'll try and drop a current copy in here for posterity, too.

Rgds

Damon

Code: [Select]
/*
Damon Hart-Davis licenses this file to you
under the Apache Licence, Version 2.0 (the "Licence");
you may not use this file except in compliance
with the Licence. You may obtain a copy of the Licence at

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing,
software distributed under the Licence is distributed on an
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
KIND, either express or implied. See the Licence for the
specific language governing permissions and limitations
under the Licence.

Author(s) / Copyright (s): Damon Hart-Davis 2016
*/

static const char *Id = "$Id: ssmppt15l-modbus.cpp 15087 2016-08-12 20:06:20Z dhd $";

/*
Stand-alone code to interrogate SS-MPPT-15L solar controller over MODBUS.
*/

#include <sys/ioctl.h>
#include <sys/param.h>
#include <sys/stat.h>
#include <sys/time.h>
#include <sys/types.h>

#include <assert.h>
#include <errno.h>
#include <fcntl.h>
#include <getopt.h>
#include <signal.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <unistd.h>

#include <modbus/modbus.h>

// Default (USB) wired serial connection to SS-MPPT-15L.
static const char *DEFAULT_MODBUS_DEV = "/dev/serial/by-id/usb-FTDI_UT232R_FTXIEVAK-if00-port0";

// Default address of the SunSaver MPPT.
static const uint8_t SUNSAVERMPPT = 0x01;

// Array volatge, filtered, units of 100*2^-15V.
static const uint16_t SS_REG_Adc_vb_f = 0x0008;
// Load voltage, filtered, units of 100*2^-15V.
static const uint16_t SS_REG_Adc_vl_f = 0x000a;
// Load current, filtered, units of 79.16*2^-15V.
static const uint16_t SS_REG_Adc_il_f = 0x000c;
// Battery voltage, slow filter (~25s), units of 100*2^-15V.
static const uint16_t SS_REG_Vb_f = 0x0013;
// Array Voc, filtered, units of 100*2^-15V.
static const uint16_t SS_REG_Sweep_Voc = 0x002a;

#ifndef __cplusplus
typedef enum { false, true } bool;
#endif

// Read single SS-MPPT-15L register into uint16_t over MODBUS; true if success.
// Potentially somewhat inefficient nominally setting up and tearing down
// connection for each read, but self-contained.
// Can automatically retry the read after a pause.
static bool getMODBUSReg(const uint16_t addr, uint16_t &value,
    const int retries = 1)
    {
    modbus_t * const ctx = modbus_new_rtu(DEFAULT_MODBUS_DEV, 9600, 'N', 8, 2);
    if(NULL == ctx)
        {
        fprintf(stderr, "Unable to create libmodbus context\n");
        return(false);
        }

    modbus_set_slave(ctx, SUNSAVERMPPT);

    if(-1 == modbus_connect(ctx))
        {
        fprintf(stderr, "Connection failed: %s\n", modbus_strerror(errno));
        modbus_free(ctx);
        return(false);
        }

    // Request specified register.
    for(int i = 0; ; )
        {
        const int n = modbus_read_input_registers(ctx, addr, 1, &value);
        if(1 == n) { break; }
        fprintf(stderr, "Bad MODBUS read: %s\n", modbus_strerror(errno));
        if(++i > retries)
            {
            fprintf(stderr, "Giving up.\n");
            modbus_free(ctx);
            return(false);
            }
        sleep(1);
        }

    /* Close the connection and free resources. */
    modbus_close(ctx);
    modbus_free(ctx);
    return(true);
    }

// Convert from MODBUS units of 100*2^-15V to mV. */
inline uint16_t fMODBUSTmV(const uint16_t vMB) { return((uint16_t) ((32767u+vMB*100000UL)>>15)); }

int main (const int argc, char *const argv [])
    {
    int c;
    while((c = getopt(argc,argv,"hv")) >= 0)
        {
        switch(c)
            {
            case 'h':
            case '?':
                {
                fprintf(stderr, "Version %s, libmodbus " LIBMODBUS_VERSION_STRING "\n", Id);
                fprintf(stderr, "%s [options]\n", argv[0]);
                fprintf(stderr, " -h this help\n");
                fprintf(stderr, " -v verbose\n");
                break;
                }
            }
        }

    // Get (smoothed/filtered) battery voltage.
    uint16_t Vb_f_raw;
    if(getMODBUSReg(SS_REG_Vb_f, Vb_f_raw))
        {
        fprintf(stdout, "Vb_f (V): %f\n", Vb_f_raw*100.0f/32768.0f);
        fprintf(stdout, "Vb_f (mV): %u\n", fMODBUSTmV(Vb_f_raw));
        }
    else { fprintf(stderr, "Failed\n"); exit(1); }

    uint16_t Adc_vb_f;
    if(getMODBUSReg(SS_REG_Adc_vb_f, Adc_vb_f))
        {
        fprintf(stdout, "Adc_vb_f (mV): %u\n", fMODBUSTmV(Adc_vb_f));
        }
    else { fprintf(stderr, "Failed\n"); exit(1); }

    uint16_t Sweep_Voc;
    if(getMODBUSReg(SS_REG_Sweep_Voc, Sweep_Voc))
        {
        fprintf(stdout, "Sweep_Voc (mV): %u\n", fMODBUSTmV(Sweep_Voc));
        }
    else { fprintf(stderr, "Failed\n"); exit(1); }

    return(0);
    }
Podcast: https://www.earth.org.uk/SECTION_podcast.html

@DamonHD@mastodon.social

DamonHD

  • Administrator
  • Super Hero Member Plus
  • *****
  • Posts: 4125
  • Country: gb
    • Earth Notes
Re: MODBUS and Raspberry Pi for Off-grid Storage Monitoring (SS-MPPT-15L)
« Reply #6 on: August 14, 2016, 12:12:07 PM »
I'm pleased to see that I'm able to pull up to about 80W (recharging my laptop) from the system without significant sag, and monitor the load, c/o the MODBUS stuff!

Rgds

Damon
Podcast: https://www.earth.org.uk/SECTION_podcast.html

@DamonHD@mastodon.social

DamonHD

  • Administrator
  • Super Hero Member Plus
  • *****
  • Posts: 4125
  • Country: gb
    • Earth Notes
Re: MODBUS and Raspberry Pi for Off-grid Storage Monitoring (SS-MPPT-15L)
« Reply #7 on: August 28, 2016, 03:51:10 AM »
I had been having some reliability issues with reading from MODBUS, possibly from the self-powered RS232/USB interface needing to charge some caps or whatever.

http://www.earth.org.uk/RPi201406/code/

Anyhow, here is the business part of the latest code:

Code: [Select]
/*
Damon Hart-Davis licenses this file to you
under the Apache Licence, Version 2.0 (the "Licence");
you may not use this file except in compliance
with the Licence. You may obtain a copy of the Licence at

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing,
software distributed under the Licence is distributed on an
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
KIND, either express or implied. See the Licence for the
specific language governing permissions and limitations
under the Licence.

Author(s) / Copyright (s): Damon Hart-Davis 2016
*/

//static const char *Id = "$Id: mbaccess.cpp 15255 2016-08-26 20:40:45Z dhd $";

/*
MODBUS access routines/wrapper.
*/

#include <sys/ioctl.h>
#include <sys/param.h>
#include <sys/stat.h>
#include <sys/time.h>
#include <sys/types.h>

#include <assert.h>
#include <errno.h>
#include <fcntl.h>
#include <getopt.h>
#include <signal.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <unistd.h>

#include "mbaccess.h"


// Default (USB) wired serial connection to SS-MPPT-15L.
const char *DEFAULT_MODBUS_DEV = "/dev/serial/by-id/usb-FTDI_UT232R_FTXIEVAK-if00-port0";

// Get process-scope cached MODBUS context/connection to SS-MPPT-15L.
// Flushes any pending input.
// Returns NULL in case of failure.
static modbus_t * const getCachedContext()
    {
    static modbus_t * const ctx = modbus_new_rtu(DEFAULT_MODBUS_DEV, 9600, 'N', 8, 2);
    if(NULL == ctx) { return(NULL); } // Failed.

    // First time only, set slave and connect to avoid multiple open() calls.
    static bool inited;
    if(!inited)
        {
        // Set the SS-MPPT-15L as the device to talk to.
        modbus_set_slave(ctx, SUNSAVERMPPT);
        // Attempt to connect; return NULL if failed.
        if(-1 == modbus_connect(ctx))
            {
            fprintf(stderr, "MODBUS: connection failed: %s\n", modbus_strerror(errno));
            return(NULL);
            }
        // Allow time for power to stabilise, etc.
        // (Our circs with RS232 inteface powered over USB...)
        // 750ms seems enough to avoid initial read timeout (500ms not).
        usleep(750000ul);
        inited = true;
        }

    // Pause/flush to allow things to settle and previous responses to clear.
    // 10ms is ~10 character times at 9600 bps;
    // typical single-register read is 7 or 8 chars.
    do { usleep(10000ul); } while(0 < modbus_flush(ctx));

    return(ctx);
    }

// Read single SS-MPPT-15L register into uint16_t over MODBUS; true if success.
// Potentially somewhat inefficient nominally setting up and tearing down
// connection for each read, but self-contained.
// Can automatically retry the read after a pause.
bool getMODBUSReg(const uint16_t addr, uint16_t &value, const int retries)
    {
    bool result = false;
    for(int t = retries; !result && (--t >= 0); )
        {
        modbus_t * const ctx = getCachedContext();
        if(NULL == ctx)
            {
            fprintf(stderr, "MODBUS: unable to create libmodbus context\n");
            return(false);
            }

        // Request specified register.
        const int n = modbus_read_input_registers(ctx, addr, 1, &value);
        if(1 == n) { result = true; }
        else
            {
            fprintf(stderr, "MODBUS: bad read: %s\n", modbus_strerror(errno));
            sleep(1);
            }
        }

    if(!result) { fprintf(stderr, "Giving up.\n"); }
    return(result);
    }

Podcast: https://www.earth.org.uk/SECTION_podcast.html

@DamonHD@mastodon.social

DamonHD

  • Administrator
  • Super Hero Member Plus
  • *****
  • Posts: 4125
  • Country: gb
    • Earth Notes
Re: MODBUS and Raspberry Pi for Off-grid Storage Monitoring (SS-MPPT-15L)
« Reply #8 on: October 01, 2016, 12:22:06 PM »
Having a ball with the MODBUS.

I seem to have fixed the reliability and speed issues that I was having, and the dump load oscillation.

I added temperature compensation (using the temperature measured at the battery by the controller's probe).  I hope that means I can safely squeak out a bit more energy when things get cold.  I will also draw battery temps against the temperature in the porch just the other side of the wall, when I get bored!

And today, to avoid doing something more tedious, I thought I'd try sampling the power system parameters every few seconds rather than every few minutes to see if just like the PV on the roof there's lots of noise at that level ... and yes there is!

http://www.earth.org.uk/MODBUS-and-Raspberry-Pi.html#20161001

Rgds

Damon



Podcast: https://www.earth.org.uk/SECTION_podcast.html

@DamonHD@mastodon.social

DamonHD

  • Administrator
  • Super Hero Member Plus
  • *****
  • Posts: 4125
  • Country: gb
    • Earth Notes
Re: MODBUS and Raspberry Pi for Off-grid Storage Monitoring (SS-MPPT-15L)
« Reply #9 on: October 02, 2016, 02:23:35 PM »
OK, I gave in and did battery bank temp vs outside.  That's what Sunday afternoons are *for*, yes?



Rgds

Damon
« Last Edit: October 02, 2016, 02:27:45 PM by DamonHD »
Podcast: https://www.earth.org.uk/SECTION_podcast.html

@DamonHD@mastodon.social

SparWeb

  • Global Moderator
  • Super Hero Member Plus
  • *****
  • Posts: 5452
  • Country: ca
    • Wind Turbine Project Field Notes
Re: MODBUS and Raspberry Pi for Off-grid Storage Monitoring (SS-MPPT-15L)
« Reply #10 on: October 04, 2016, 11:07:55 PM »
It gives you a picture of the thermal "lag" through an insulated wall, doesn't it?
I get similar results between my outdoor temps and batt bank temperatures.

Different battery chemistries have different temperature correction factors.  I think Gel cells also have a voltage limit, at which the temp compensation should be capped.  There are clear instructions in my old Xantrex C40 controller manuals - you may be able to find applicable limits for your batteries.
No one believes the theory except the one who developed it. Everyone believes the experiment except the one who ran it.
System spec: 135w BP multicrystalline panels, Xantrex C40, DIY 10ft (3m) diameter wind turbine, Tri-Star TS60, 800AH x 24V AGM Battery, Xantrex SW4024
www.sparweb.ca

DamonHD

  • Administrator
  • Super Hero Member Plus
  • *****
  • Posts: 4125
  • Country: gb
    • Earth Notes
Re: MODBUS and Raspberry Pi for Off-grid Storage Monitoring (SS-MPPT-15L)
« Reply #11 on: October 05, 2016, 02:25:20 AM »
The wall is not insulated (single row of breeze blocks) but I have partly insulated the battery bank as described in another thread.  The big thermal mass and the insulation will indeed make for a lag.

I did finally locate my battery spec sheet last week, about 7 years late, but I think my Morningstar controller is doing the right thing on 'gel' settings, so I'm leaving it be!

Rgds

Damon
Podcast: https://www.earth.org.uk/SECTION_podcast.html

@DamonHD@mastodon.social