3G Bandwidth

I connected emonbase to mobile broadband router and measured uplink data for one day @ nearly 70MB. Configuration was one emontx with 3 CT and 1 Pulse sensors connected to emonbase and ethernet into mobile broadband router.

Can this uplink data throughput be reduced in order to reduce costs?

Thanks

Peter

Robert Wall's picture

Re: 3G Bandwidth

Can you clarify? You have posted the emonTx sketch, but you are saying that you have connected the emonBase to the 3G modem/router.

The general answer to your question is yes. You can reduce the data that is sent either by reducing the message length or the frequency, or both. You need to decide what data you need to send and how often it needs updating, then modify (or rewrite) the sketch in the emonBase. For example, instead of simply relaying the data from the emonTx immediately it is received, you could over (say) a 5 minute window accumulate the real and apparent powers and pulse count, record min and max and calculate average voltage and currents, then at the end of the window transmit that over the 3G link. There are innumerable variations on that theme that you could try (e.g. send after 5 minutes or when there is a large change, whichever is the sooner). It all depends on what you are doing and what information you want at the other end.

PeterN's picture

Re: 3G Bandwidth

Thanks Robert. Not quite as simple as described above I'm using emonbase connected to ethernet bridge wifi and 3G router with a free 3G dongle. My Mobile phone package includes 1GB data a month so I been using my SIM for testing. Once I overcome the data bandwidth issue I plan to build 3G solution based on openwrt.

Your suggestion sounds good, it will not only reduce bandwidth but also reduce the frequency of data transfer.  I'm new to programming so it may take me a few days, I'll keep you posted.

 

Robert Wall's picture

Re: 3G Bandwidth

OK, here's (roughly) how I'd approach it. I'm looking at the sketch NanodeRF_Power_RTCrelay_GLCDtemp.ino

At the top you'll need to declare new variables for the quantities you want to accumulate (the same types as the individual values, or maybe larger versions - long instead of int - if there's a danger they will overflow) plus a time that the window will close (type: unsigned long).

In setup() you need to set those to zero. You also need to get the current time and decide when to close the window window_endtime = millis() + 300000;  or similar (5 minutes in milliseconds) - look at the Arduino language reference documentation for what millis() is and does.

In loop() after you have received the numbers by radio  if (rf12_recvDone()){ and they are from the right place if (node_id == 10) then you can accumulate the powers, like accum_power1 += emontx.power1; (I'd put this after the str.print() statements, which you no longer need, so these can be commented out).

When you have all those, you need to see if it's time to send them and close the window. Do this where the data is sent to the Ethernet. Check whether it is time to do it, if so do it.

if (millis() > window_endtime) {
   str.print("{rf_fail:0");
   str.print("Power1:");
   str.print(accum_power1);

etc and finish with

   str.print("}\0");  //  End of json string

then you need to set

   window_endtime = millis() + 300000; 

again and zero all the accumulators before closing the "if"

}

 

You might want to send similar stuff (or more) to the serial port ( Serial.print( ..... ) ) to enable you to debug without costing bandwidth. You might also want or need to send the actual window length if you do more calculations at the receiving end.

The big disclaimer: I HAVE NOT TRIED THIS. I DON'T GUARANTEE IT EVEN MIGHT WORK. It is how I would start. I hope it gives you a bit of a steer.

One problem I'd need to check up on - what happens when millis() rolls over and starts again from zero. I think how I've done it should work, but you'll have to run it for 7 weeks to find out!

[Edit]  No, it won't work properly within one window of millis() rolling over, because window_endtime will have rolled over and will be just greater than zero while the value returned by millis() will be 2^32 less a bit!  So it will send data continuously until millis() does roll over. It needs some extra logic to detect window_endtime rolling over and inhibit the transmission until millis() has done so too.

PeterN's picture

Re: 3G Bandwidth

Thanks a mil. I adapted the lastest version of NanodeRF_Power_RTCrelay_GLCDtemp sketch based on your comments above. I was unable to get millis() working so used  "for(int i = 0; i < 10 ; i++) // to count 10 readings"  e.g. 10 RF readings and then I averaged. It seems to be working ok as I checked by changing the number of samples and looking for corresponding decrease in average ( and then set back to correct value) . I was getting some negative values -changed to unsigned long rectified this.

However the average value is still updating every twenty seconds. Attached is modified sketch. Any other ideas or have I taken wrong approach. Please excuse my programming.

 

 

Robert Wall's picture

Re: 3G Bandwidth

I think from what I can see, you are struggling with the basic concept behind the Arduino software. When you first get your Arduino processor (or maybe this has been done for you before you get it), you load a program called a 'bootloader'. In effect this is the Windows/Linux/OSX/Android of the Arduino. As far as you are concerned, it does two things. It calls a function called setup( ), then it repeatedly calls a function called loop( ). (It does other things, but those don't concern you here).

What you have to do is work within that framework.

What I was trying to do with millis() (and unfortunately, you haven't left your attempt to use it in so I can't see why it didn't work for you), was to remember a time when it started, then accumulate values for a length of time after that, then the first time round the loop after the time was up, do something with those accumulated values. But you have to do this within the constraints of the main loop. What you actually did with the for (..;..;..) loop that you inserted was to short-circuit this. In fact, because you did not let the main loop run, you added up the same emontx.power1 etc 10 times.

Here is a very stripped-down version of what you want. You need to merge this with the original:

#define WINDOW 180000          // 3 minutes x 60 seconds x 1000
unsigned long window_endtime;
unsigned long accum_pulse;
long accum_power1;
unsigned int num_readings;

void setup () {
   accum_pulse = 0;
   accum_power1 = 0;
   num_readings = 0;
   window_endtime = millis() + WINDOW;
}
void loop() {
  if (rf12_recvDone()){      
      if (rf12_crc == 0 && (rf12_hdr & RF12_HDR_CTL) == 0)
      {
        int node_id = (rf12_hdr & 0x1F);
        
        if (node_id == 10)                                                    // EMONTX
        {
          emontx = *(PayloadTX*) rf12_data;                    // get emontx data
          // accumulate readings each time round loop( )
         accum_pulse += emontx.pulse; // accumulate readings - this is not averaged as total pulse is used.
         accum_power1 += emontx.power1;                   // accumulate readings
         num_readings++;                                                  // and count them
       }     // end of "if (nodeid( ... )"
    }     // end of "If (rf12_crc ..."
  }      // end of (if rf12_recv ....)
  if (millis() > window_endtime)                                    // if we are past the end of the window, do this,
                                                                                            // whether we are receiving values or not.
  {
    Serial.print("accumpulse");Serial.println(accum_pulse);     // Send the numbers to wherever
    Serial.print("averagepower");Serial.println(accum_power1/num_readings);
    accum_pulse = 0;                                                        // start a new window
    accum_power1 = 0;
    num_readings = 0;
    window_endtime = millis() + WINDOW;                
  }  // end of "if (millis()... ) "
}   // end of "loop()"

 

Give me a day or two and I'll try to rewrite your sketch and test it (so you need to subscribe to this thread or keep watching).

In the meantime, check out millis() and see where you went wrong. If you really want to count readings instead of time, then instead of    if (millis() > window_endtime)   you need   if (num_readings > 10 )  or whatever number you wish.

PeterN's picture

Re: 3G Bandwidth

Thanks again for detailed explanation, I'll work on this over weekend, your time and effort is much appreciated.

Just to confirm I'm using latest Arduino IDE 1.01 for windows, uploading via FTDI, programmer set to AVRISP MK11 and board set to UNO. I tend to use standard sketchs and modify them then compile/verify and upload using IDE. The libraries seem straight forward and are always included in sketch read TXT, anyway this is always verified before upload.

Note I'm assuming I don't need to do anything with bootloader as I not using USB??? is this correct?

This project and your very well written explanation should help me along the path to better understanding  code.

Cheers

Peter

Robert Wall's picture

Re: 3G Bandwidth

"Note I'm assuming I don't need to do anything with bootloader as I not using USB??? is this correct?"

I wouldn't want to mess with the bootloader! 

No, stay clear. I'm using USB as a serial port to FTDI to program and read the serial data, and I've not touched the bootloader. You have to really know what you're doing in there.

(I've just installed 1.0.1 - having not had chance to install it! - and I was just about to load a test sketch into the emonTx so that I'd have something to work with. Then I'll edit your sketch and get it going.

 

Robert Wall's picture

Re: 3G Bandwidth

Try this. I have not been able to test it fully because I didn't have access to your server, however it does seem to be doing roughly what you want.

PeterN's picture

Re: 3G Bandwidth

Great work thanks a mil. Tried above and worked first time. I did notice some very high number when rf fails. I will test further tonight and post results.

Robert Wall's picture

Re: 3G Bandwidth

I'm not sure I bothered too much about the failure mode! My main aim was to point you in the right direction. (You do understand now how  loop( ) works and how you need to pick out when to do timed things?). Obviously if the rf fails, you need to recognise that and do something sensible rather than just ignore it. What you do depends on what you want - e.g do you assume zero, or power remains constant, or just freeze the average? Your choice.

PeterN's picture

Re: 3G Bandwidth

Yes thanks. You have definitely helped me understand code a lot better. Cheers

Peter

PeterN's picture

Re: 3G Bandwidth

Thanks

Comment viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.