Tuesday, 12 September 2017

Internet of Things: Solar Battery Voltmeter

Get solar battery voltage now

From the last post, we have a car battery being charged by a solar panel, and to monitor the battery voltage we have a Raspberry Pi with a WiPi (USB WiFi dongle for the Pi) with an added USB serial port dongle hacked as a voltmeter.

Solar panel charging a car battery


Quick, basic way to present information in the Internet of Things


Now I can log into my Pi remotely through wifi:

ssh -t 172.16.1.10

A python program can be written very quickly, say solarbat.py:
#!/usr/bin/python
import serial
from time import localtime, strftime

port=serial.Serial('/dev/ttyACM0', timeout=1)

if __name__ == "__main__":

  port.write('A')
  Vbat= port.read(10)
  Battery_Voltage=int(format(ord(Vbat[0]), '02x'), 16)*256 + \
                  int(format(ord(Vbat[1]), '02x'), 16)
  if Vbat[2:5] != 'HCM':
    print 'Checkbyte Fail' 

# Calibrated_Battery_Voltage = Battery_Voltage * 12.56 / 640
  Calibrated_Battery_Voltage = Battery_Voltage * 13.75 / 689

  print Calibrated_Battery_Voltage,'Volts',strftime("%Y-%m-%d %H:%M:%S", localtime())


When executed:
root@piface1:/home/heong/analog_pic# ./solarbat.py
12.893625 Volts 2017-09-06 13:48:55

Technically speaking it is an Internet of Things device now. I have set up my modem router to host my website www.cmheong.com, and if you logged into my webhost, you could now remotely trigger the battery voltage measurement and retrieve the result:

$ ssh -t root@172.16.1.10 /home/heong/analog_pic/solarbat.py
root@172.16.1.10's password:
12.91325 Volts 2017-09-06 13:52:24
Connection to 172.16.1.10 closed.

A bash script can be set up in the webserver to log in automatically, execute solarbat.py and retrieve the results. What bash can do, an Android smartphone can. 

And there you have it, a first cut of an IoT Solar Battery meter.
It is more common to expose this functionality via a network socket, and for this to happen we need two more programs, a server program to run solarbat.py on the Pi, and to forward the results to the webserver.

The webserver runs a client program using a PHP script. The script runs client program to extract and displays the results.

I got some sample code from here (honestly I have never done this before and all it took was a couple of hours). The client code is unmodified:

#include <sys/socket.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <netdb.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <arpa/inet.h> 

int main(int argc, char *argv[])
{
    int sockfd = 0, n = 0;
    char recvBuff[1024];
    struct sockaddr_in serv_addr; 

    if(argc != 2)
    {
        printf("\n Usage: %s <ip of server> \n",argv[0]);
        return 1;
    } 

    memset(recvBuff, '0',sizeof(recvBuff));
    if((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0)
    {
        printf("\n Error : Could not create socket \n");
        return 1;
    } 

    memset(&serv_addr, '0', sizeof(serv_addr)); 

    serv_addr.sin_family = AF_INET;
    serv_addr.sin_port = htons(5000); 

    if(inet_pton(AF_INET, argv[1], &serv_addr.sin_addr)<=0)
    {
        printf("\n inet_pton error occured\n");
        return 1;
    } 

    if( connect(sockfd, (struct sockaddr *)&serv_addr, sizeof(serv_addr)) < 0)
    {
       printf("\n Error : Connect Failed \n");
       return 1;
    } 

    while ( (n = read(sockfd, recvBuff, sizeof(recvBuff)-1)) > 0)
    {
        recvBuff[n] = 0;
        if(fputs(recvBuff, stdout) == EOF)
        {
            printf("\n Error : Fputs error\n");
        }
    } 

    if(n < 0)
    {
        printf("\n Read error \n");
    } 

    return 0;
}

The server code I modified to invoke solarbat.py when a client request triggers it:

#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <sys/types.h>
#include <time.h> 

int readfile(char *buffer, int maxsize)
{
  FILE *fileread = NULL;
  char *filename = "solarbat.txt";
  unsigned int i = 0;

  fileread = fopen(filename, "r");

  if(fileread == NULL)
  {
    int saved_errno=errno;
    if(saved_errno == ENOENT)
      printf("File %s does not exist\n", filename);
    else
      printf("errno is %d\n", saved_errno);
    buffer[0]=0;
    return 0;
  }
  else
  {
    // printf("%s successfully opened, reading file ...\n", filename);
    while(!feof(fileread)) // read only the last line
      i=fread(buffer, 1, maxsize, fileread);
    if (i<maxsize) // terminate string for printf
        buffer[i] = 0;
    else
        buffer[maxsize]=0;
    fclose(fileread);
    return i;
  }
}

int main(int argc, char *argv[])
{
    int listenfd = 0, connfd = 0;
    struct sockaddr_in serv_addr; 

    char sendBuff[1025];
    char readBuff[1025]; // cmheong 2017-09-11

    time_t ticks; 

    listenfd = socket(AF_INET, SOCK_STREAM, 0);
    memset(&serv_addr, '0', sizeof(serv_addr));
    memset(sendBuff, '0', sizeof(sendBuff)); 

    serv_addr.sin_family = AF_INET;
    serv_addr.sin_addr.s_addr = htonl(INADDR_ANY);
    serv_addr.sin_port = htons(5000); 

    bind(listenfd, (struct sockaddr*)&serv_addr, sizeof(serv_addr)); 

    listen(listenfd, 10); 

    while(1)
    {
        connfd = accept(listenfd, (struct sockaddr*)NULL, NULL); 

        system("/home/heong/analog_pic/solarbat.py > ./solarbat.txt");
        readfile(readBuff, 1024);

        snprintf(sendBuff, sizeof(sendBuff), "%s", readBuff);
        write(connfd, sendBuff, strlen(sendBuff)); 

        close(connfd);
        sleep(1);
    }
}

To compile, you do (in Pi):
gcc -o solar_server solar_server.c

Over at your web server you do:
gcc -o client client.c

This seems a bit pedantic but it takes care of the different systems- the Pi is an ARM system and the webhost can be an Intel-based blade server.

To execute, you run on the Pi:
 ./solarbat_server

Over on client you do (assuming 172.16.1.10 is the address of the Pi):
 ./client 172.16.1.10
Mon Sep 11 14:15:45 2017

The last step is the php script. solarbat.php

<!DOCTYPE html>
<html>
<body>

<?php
echo "<h2>Solar Battery Voltage</h2>";
$last_line = system('/home/heong/socket/client 172.16.1.10', $retval);
//echo $last_line;
?> 

</body>
</html>

Now to get the solar battery measurement you only need to aim your browser at the script:

http://www.cmheong.com/solar/solarbat.php

Should get you this screenshot:


The Internet of Things is that simple. Happy Trails

Update Thu 14 Sep 2017: yesterday the weather was overcast a good part of the afternoon (the panel faced west) and the battery did not charge up properly. Over the night, the Raspberry Pi completely discharged the battery and only restarted the morning of the 14th when the sun came up. The php link stopped working - my apologies.

The voltmeter readings themselves told the story:


Take your PIC

The Microchip PIC microcontrollers are amazing.  I encountered them back in 1998, and they are game changers for digital electronics. They are cheap (and I mean throwaway cheap), easy to power (they have wide operating voltages, have very versatile I/O and are surprisingly powerful.

One of many incarnations of the PIC24. Photo by Acdx


The 'F' series (PIC16F, PIC18F, PIC24F) were electrically re-programmable. They also have eeprom, which means you can retain parameters and data after power-off. Best of all Microchip provided a free (rare at the time) subset of development tools, including sample code.

Dinosaurs- ultra-violet light erasable PICs. Photo from wikipedia


It now made no sense to use timer ICs like the CD4040, or even the iconic LM555 or multivibrators like the 74121. A PIC is much more precise, does not drift over time, and more consistent, especially for production units. For me, it even replaced small-scale FPGA. For an old assembly language jock (my first computer language was solder!), it was heaven-sent.

The PIC18F14K50 is one of the first USB microcontrollers. It came with a free subset of the MPLAB IDE and you can get it to work with a C compiler. Best of all there is a lot of C source code, for many types of USB Device, USB Hosts and USB OTG. The flash programmer Pickit 2 was cheap, especially the third-party versions.
The USB interface is the current de facto interface standard, and was well worth the investment in time from 15 years ago. Microchip's Low Pin Count Development Kit was cheap and can be deployed with minimal modifications.

Left: USB-RS485 interface 
Right: Low Pin Count Development Kit. 
The USB RS485 dongle is my design, a slightly modified derivative of the Microchip Low Pin Count Development Kit. It is based on the PIC18F14K50 microcontroller. The following work also applies to the Low Pin Count Development Kit. The advantage is that it is compatible with the existing Windows and Linux device drivers: both Windows and Linux will automatically recognize it as a garden-variety USB serial port. We thus avoid the need to write custom device drivers (although writing device drivers can be fun and profitable- perhaps the subject of another post).


PIC18F14K50-based RS485 USB dongle and the PICKIT2 programmer
The intention is to use the USB RS485 dongle, together with the Raspberry Pi to measure the battery voltage at my solar panel. This is gross overkill for an embedded voltmeter, but as we shall see, it expands into an Internet of Things device. And by having the device come up as a standard USB serial port, we again avoid the need for custom Linux and Windows device drivers.

It would be a strange serial port. When sent any valid character, the device will respond with:
byte1 byte2 'HCM' byte3 byte4 'LJP'. 

Where byte1 and byte2 are hexadecimal bytes from AN8 and similarly, byte3 and byte4 are hexadecimal bytes from AN9. The PIC's Analog-to-Digital Converter is 10-bits, so 2 bytes are required for each input.

USB RS485 dongle with added resistor divider circuit

USB RS485 dongle with Raspberry Pi, mounted as an IoT solar battery voltmeter

My version of MPLAB only runs on Windows (you might have better luck with the newer MPLAB X), so I usually run it from my Qemu Virtual Machine. I then copy the compiled hex file and program it using pk2cmd.

Screenshot of Slackware 14.2 Linux running MPLAB 8.3 Windows XP on a Qemu  Virtual Machine

The sample code I am using is the Microchip USB Device - CDC - Serial Emulator. There is an online version here, but I would recommend you download the Microchip version.

The PIC18F14K50 has 9 usable external analog input lines. We only need two, one for the battery and one for the solar panel. We use AN8 and AN9, just because they happen to be unused and easily soldered on the PCB.

We find the file main.c in the sample code and insert the following lines of C code to initialize the PIC:

void InitializeUSART(void)
{
    #if defined(__18CXX) // __18CXX *is* defined
            unsigned char c;
        #if defined(__18F14K50)
            TRISC |= 0x30; // Set up AN8 AN9 for analog in
            ANSELH = 0x03; // Enable AN8-AN9, RB4, RB5
                           // we use RB4 for MAX485 RE (receiver enable)
            ANSEL = 0x00;  //Disables A4-A7 (enables RC0-RC3 for USB LEDs)
            ADCON2 = 0x9D; // Right-justified output, 6TAD
            ADCON1 = 0x00; // Vdd & Vss as +ve & -ve voltage references
            ADCON0 = 0x21; // Select AN8 (CHS=1000) and turn on ADC

Next we find the function ProcessIO() and insert:

#if defined(__18CXX)
    #define mDataRdyUSART() PIR1bits.RCIF
    #define mTxRdyUSART()   TXSTAbits.TRMT
    #define mAN8Busy()   ADCON0bits.GO 
#elif defined(__C30__) || defined(__C32__)
    #define mDataRdyUSART() UART2IsPressed()
    #define mTxRdyUSART()   U2STAbits.TRMT
#endif

void ProcessIO(void)
{
  //Blink the LEDs according to the USB device status
  BlinkUSBStatus();
  // User Application USB tasks
  if((USBDeviceState < CONFIGURED_STATE)||(USBSuspendControl==1)) return;

  if (RS232_Out_Data_Rdy == 0)  // only check for new USB buffer if the old RS232 buffer is
  {               // empty.  This will cause additional USB packets to be NAK'd
    LastRS232Out = getsUSBUSART(RS232_Out_Data,64); //until the buffer is free.
    if(LastRS232Out > 0)
    {
      RS232_Out_Data_Rdy = 1;  // signal buffer full. Any amount of data will do
      RS232cp = 0;  // Reset the current position
      mLED_3_On();  // 2017-09-03 test code
      mLED_4_Off(); // 2017-09-03 test code
    }
    else
    {
      mLED_3_Off();  // 2017-09-03 test code
      mLED_4_Off();  // 2017-09-03 test code
    }
  }

  if(RS232_Out_Data_Rdy && !mAN8Busy() && RS232cp==0 ) // 2017-09-03 Received command, ADC is free
  {
    ADCON0 = 0x21; // 2017-09-03. Select AN8 (CHS=1000) and turn on ADC
    ADCON0bits.GO = 1; // Start conversion
    ++RS232cp;    // Indicate pending conversion
    mLED_3_On();  // 2017-09-03 test code
    mLED_4_On(); // 2017-09-03 test code
  }

  if(RS232_Out_Data_Rdy && RS232cp==1) // 2017-09-03 check if conversion done
  {
    if (!mAN8Busy())
    {
      USB_Out_Buffer[NextUSBOut++] = ADRESH; // Pick up results
      USB_Out_Buffer[NextUSBOut++] = ADRESL; // Pick up results
      USB_Out_Buffer[NextUSBOut++] = 'H'; // Pick up results
      USB_Out_Buffer[NextUSBOut++] = 'C'; // Pick up results
      USB_Out_Buffer[NextUSBOut++] = 'M'; // Pick up results
      USB_Out_Buffer[NextUSBOut] = 0;
      RS232cp++; // 2017-09-04 Signal ready for next command
      mLED_3_Off();  // 2017-09-03 test code
      mLED_4_On(); // 2017-09-03 test code
    }
  }
  if(RS232_Out_Data_Rdy && !mAN8Busy() && RS232cp==2 ) // 2017-09-04 Do AN9
  {
    ADCON0 = 0x25; // 2017-09-04. Select AN5 (CHS=1001) and turn on ADC
    ADCON0bits.GO = 1; // Start conversion
    ++RS232cp;    // Indicate pending conversion
    mLED_3_On();  // 2017-09-03 test code
    mLED_4_On(); // 2017-09-03 test code
  }

  if(RS232_Out_Data_Rdy && RS232cp==3) // 2017-09-03 check if conversion done
  {
    if (!mAN8Busy())
    {
      USB_Out_Buffer[NextUSBOut++] = ADRESH; // Pick up results
      USB_Out_Buffer[NextUSBOut++] = ADRESL; // Pick up results
      USB_Out_Buffer[NextUSBOut++] = 'L'; // Pick up results
      USB_Out_Buffer[NextUSBOut++] = 'J'; // Pick up results
      USB_Out_Buffer[NextUSBOut++] = 'P'; // Pick up results
      USB_Out_Buffer[NextUSBOut] = 0;
      RS232_Out_Data_Rdy = 0; // Signal ready for next command
      mLED_3_Off();  // 2017-09-03 test code
      mLED_4_On(); // 2017-09-03 test code
    }
  }

  if((USBUSARTIsTxTrfReady()) && (NextUSBOut > 0))
  { // Send results to USB
    putUSBUSART(&USB_Out_Buffer[0], NextUSBOut);
    NextUSBOut = 0;
    mLED_3_Off();  // 2017-09-03 test code
    mLED_4_Off(); // 2017-09-03 test code
  }

  CDCTxService();
}               //end ProcessIO

Now you might notice that a lot of the code has to do with serial IO, which is not necessary for our analog to digital conversion. This will come in hand later as we refine our PIC IoT to work without the Raspberry Pi. Without the Pi as the USB host we will need to transmit our result using the serial port.

We then compile the modified sample code into a hex file which we then program using the Pickit 2:
./pk2cmd -PPIC18F14K50 -Fanalog_pic.hex  -M

If the stars are all aligned and everything goes perfectly (more likely after hours of painful but ultimately satisfying debugging) you get the correct blinkenlights on your development kit, and the PIC comes up as '/dev/ttyACM0'. We proceed to the next part, the application program to read the 'serial' port.

We whip out our python interpreter:

root@aspireF15:/home/heong/mpg$python
Python 2.7.11 (default, Mar  3 2016, 13:35:30)
[GCC 5.3.0] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> import serial
>>> port=serial.Serial('/dev/ttyACM0', timeout=1)
>>> port.write('A'); port.read(10)
1
'\x00\x00HCM\x00\x00LJP'

OK, we have a valid reply but is reading zeroes in out analog input. Time to connect AN8 and AN9 to a reference voltage, 5V.

>>> port.write('A'); port.read(10)
1
'\x03\xedHCM\x00\x00LJP'

With multimeter, AN8 measures 4.94V and the 5V rail measures 5.01V. Assuming 3ff(1023) is 5.01, so 3ed is 1005, we have 4.92V (1005 / 1023 * 5) which is pretty close!

Next we look to measuring the solar battery voltage, which we expect to be around 12V. We will need a voltage divider.

Use 10K resistor for Z1 and 3K resistor for Z2

If we use 10K and 3K resistors, this will allow for a 22V maximum at the solar panel. You should use 1% tolerance wire-wound resistors. I happened to have only 20% carbon film resistors, so I used those and hope the error can be calibrated away. Note the carbon resistors should be much worse over temperature and age. 

After some hurried programming with the solder programming language, we connect the USB pic to the battery positive and negative terminals (watch it- reversing the connection may fry your USB device or your laptop!) and we now get:

>>> port.write('A'); port.read(10)
1
'\x03\x18HCM\x00\xdfLJP'

0318 hex is decimal 792. If full-scale is hex 3ff (decimal 1023). Estimating full-scale as 5V x 13/3, and calculating 792/1023 * 5 * 13 / 3 or 16.8V. With voltmeter I get 15.19. Which is not brilliant, but reasonable.

This has been my longest post to date. I hope it did not look too difficult - it really isn't. There may be many new things like microcontrollers (PICs), USB, and python, but the sample code from the Low Pin Count Development Kit really does work out of the box. I do not know everything mentioned here 100%. I know just enough to get the project going, and that is the norm in these manic days of ever-diminishing cycle time.

In the next post I will link up the analog input USB PIC18F14K50 to my website, and this makes it part of the Internet of Things.

Good luck and happy trails.

Saturday, 9 September 2017

The Itinerant Solar Panel

Sometime back we visited Bernard Ng's orchard where he showed me his solar power rig, and I know I got to have one. I bought the same make of solar panel, SC Origin's 100W SPM100-M. I was quite pleased with it; so pleased that after two years in the guest room it was time it got mounted.

Solar panel facing west

I did not want a permanent mounting yet- the idea was to experiment with different locations and angles and collect data on the amount of charge I can collect from it. It needed to be stable enough not to get blown over, yet portable enough to be moved. At first I got a solar mounting frame:


But moving it was a little fraught. I found myself wrapping the panel in bubble wrap before moving it.

I finally settled on a very cheap (about RM60) plastic table, very common in Malaysia.


I simply unscrewed the table top from its metal base and mounted the solar panel in its place. The plastic table top disappeared under my 1969 Volkswagen Beetle as an oversized oil pan.

The solar panel needed to be mounted at an angle sometimes, and I nailed together a few bits of wood to hold it in place (otherwise the table tends to snap shut in the fully-folded position). To hold everything down, I made the wooden brace to fit the base of the battery. I used an NS60 sealed lead acid car battery.



Lastly the panel and battery needed to be connected to a solar charge controller, the 5A Gamma 2.0.
And mounted in place:

The Gamma came with an after-dark timer, so I connected a 35mA 12V LED night light to it.

Here is a charging graph, over some three days and two nights. The panel faced west so the morning charging starts slow, ramping up from 2pm until 6pm. The battery voltage here is seen to go well over the maximum 13.8V.

The discharging slope corresponds to the 35mA nightlight as well as a Raspberry Pi Model A (the original one) as well as a derivative of the Microchip Low Pin Count Development Board, probably 200mA or so in total.

By adding a WiFi USB dongle, the Wi Pi by Element14, we get a very rough-and-ready first version of an Internet of Things Solar Battery Voltage Monitor, which is the subject of the next post, so stay tuned!

Wednesday, 9 August 2017

"3G MiFi Modem Car Wifi Router", Lithium Batteries and the Internet of Things

The Internet of Things quite simply is when your devices (TV, house alarm, automatic gate, refrigerator, etc) get on the Internet.

The official definition doesn't seem to sound as pithy: "the inter-networking of physical devices, vehicles (also referred to as "connected devices" and "smart devices"), buildings, and other items embedded with electronics, software, sensors, actuators, and network connectivity which enable these objects to collect and exchange data".

This post is about the "inter-networking" portion, where your house devices use a gateway to get on the Internet. A "cookie-cutter" gateway can be made very cheaply by using a tiny Linux computer connected via WiFi to your house broadband (ADSL) modem.

I like the Raspberry Pi and the beaglebone. Both are capable of running standard, full-size Linux, especially the Slackware Linux distribution (OK, so I am an old geezer).

These computers are powered from your smartphone charger, and by extension the power bank. Best of all they are cheap. Technically they are overkill as IoT controllers, but they are fun and they are full Linux (you get python!) and hardware gets cheaper every year so unless you cannot afford the electrical power do try them out.

Beaglebone White (left) and Raspberry Pi with PiFace cape
For sustained (and I mean months on end) use, I prefer the beaglebone. The Raspberry Pi despite its many improvements and upgrades use the Broadcom chipsets which have USB ports that are much less reliable. And the Pi uses Broadcom USB for both its copper LAN and its WiFi interface which no amount of clever software can work around.

For some 3 years now I have been running IoT systems at remote sites. This lets me remotely access my systems from my study or my office. It is not always possible to get telephone landline ADSL, but usually there is a cellphone reception that is good enough. I just need to change my gateway to a 3G modem-router.

The first 3G modem routers I used had lithium batteries in them. I did not need the batteries as I had mains power, but they would not start up without the batteries. These batteries tend to fail, often because I had them on all the time in non-airconditioned places.

The D-Link DWR-730 with battery dismounted(top). Notice it is bulging in the middle 
TP-Link TL-MR3040 with attached 3G dongle. Notice the failed battery, which overheated whenever in use.

It was time to get one which did not have a lithium battery and I settled on the no-brand "3G Mifi Modem Car Wifi Router Mini Wireless Routers Unlock Modem with SIM Card Slot". The English seemed a little dodgy but hey, it was cheap (only RM78) and it did not have a lithium battery.


3G Mifi, reallr a WR-706

It arrived without a manual but had a crumpled scrap of paper with 2 lines scribbled on it.



I removed the cover and installed the SIM card with some difficulty: there were 4 positions that fit but only 1 correct position.

3G Mifi with SIM card installed. This is the only correct position
I powered it on from my smartphone charger cable, pressed the power button and ... nothing. But we engineers are bigger than mere manuals, and after much tinkering found that I had to hold down the power button for a few seconds before it will turn on.

From my laptop I looked for a new WiFi hotspot using the command 'iwlist wlan0 scan'

iwlist wlan0 scan
          Cell 03 - Address: 02:03:7F:95:6E:E5
                    Channel:6
                    Frequency:2.437 GHz (Channel 6)
                    Quality=68/70  Signal level=-42 dBm
                    Encryption key:on
                    ESSID:"MIFI_WR706_EE5"
                    Bit Rates:1 Mb/s; 2 Mb/s; 5.5 Mb/s; 6 Mb/s; 9 Mb/s
                              11 Mb/s; 12 Mb/s; 18 Mb/s
                    Bit Rates:24 Mb/s; 36 Mb/s; 48 Mb/s; 54 Mb/s
                    Mode:Master
                    Extra:tsf=0000000001c2176f
                    Extra: Last beacon: 5273ms ago
                    IE: Unknown: 000E4D4946495F57523730365F454535
                    IE: Unknown: 010882848B0C12961824
                    IE: Unknown: 030106
                    IE: Unknown: 0706555320010B1B
                    IE: Unknown: 2A0100
                    IE: Unknown: 32043048606C
                    IE: WPA Version 1
                        Group Cipher : TKIP
                        Pairwise Ciphers (2) : CCMP TKIP
                        Authentication Suites (1) : PSK
                    IE: IEEE 802.11i/WPA2 Version 1
                        Group Cipher : TKIP
                        Pairwise Ciphers (2) : CCMP TKIP
                        Authentication Suites (1) : PSK
                    IE: Unknown: DD180050F2020101000003A4000027A4000042435E006232
2F00
                    IE: Unknown: DD640050F204104A0001101044000102103B000103104700
101AFAD653631652ECB2FC1CF677E2E230102100085155414C434F4D4D10230006415236303078102
400012010420001201054000800060050F2040001101100074152364B2D415010080002010E

Aha, MIFI_WR706_EE5 was exactly what was scribbled on that scrap of paper. The next line was 1234567890 which I took to be the password. This lets me produce a wifi configuration file /etc/wpa_supplicant.conf as:

cat /etc/wpa_supplicant.conf
ctrl_interface_group=0
eapol_version=1
ap_scan=1
fast_reauth=1
#country=US
# WPA protected network, supply your own ESSID and WPAPSK here:
network={
  scan_ssid=1
  ssid="MIFI_WR706_EE5"
  proto=WPA RSN
  key_mgmt=WPA-PSK
  pairwise=CCMP TKIP
  group=CCMP TKIP
  psk="1234567890"
  priority=10
}

Next you run the command:
wpa_supplicant -d -Dwext -iwlan0 -c/etc/wpa_daisy.conf -B

You check the results with
wpa_cli -iwlan0 status

And you get:

bssid=02:03:7f:95:6e:e5
freq=0
ssid=MIFI_WR706_EE5
id=0
mode=station
pairwise_cipher=CCMP
group_cipher=TKIP
key_mgmt=WPA2-PSK
wpa_state=COMPLETED
ip_address=192.168.1.32
address=c8:ff:28:27:7d:2b
uuid=29de4b6d-135e-5be0-a3c3-0db44f618230

Next you do:

dhclient -v -1 wlan0
Listening on LPF/wlan0/c8:ff:28:27:7d:2b
Sending on   LPF/wlan0/c8:ff:28:27:7d:2b
Sending on   Socket/fallback
DHCPDISCOVER on wlan0 to 255.255.255.255 port 67 interval 6
DHCPDISCOVER on wlan0 to 255.255.255.255 port 67 interval 14
DHCPDISCOVER on wlan0 to 255.255.255.255 port 67 interval 18
DHCPDISCOVER on wlan0 to 255.255.255.255 port 67 interval 16
DHCPREQUEST on wlan0 to 255.255.255.255 port 67
DHCPOFFER from 192.168.1.1
DHCPACK from 192.168.1.1
bound to 192.168.1.32 -- renewal in 33585 seconds.

And we have liftoff! The last output showed us that the 3G Mifi's IP address was 192.168.1.1, so I fired up my firefox browser and typed into it:
http://192.168.1.1

And got a rude shock- it's setup screen was in Chinese! Engineer or not, it is time to RTFM! 

Screenshot of the language change screen

That explains the dodgy English. If you moved the mouse around the browser screen it sometimes tells you(at the bottom of the browser) what is clickable. For example right at the top, the white-and-green icon resulted in  'http://192.168.1.1/Userguide_zh_v2.pdf'. Clicking on that produced a manual, but in in Chinese. 

Now websites (specifically HTML) often use languages codes to tell the browser what language to use, and 'zh' means Chinese, so I typed into the browser 'http://192.168.1.1/Userguide_en_v2.pdf' and sure enough an English manual popped up. You can download it here.

From there I discovered that the admin password was 'password', and this unlocked the other screens for me. Now with the manual, I calmed down enough and remembered I am Chinese too: the bit you want to click on is the third horizontal white bar from the top. That is a drop-down menu with 3 selections. Select the topmost one for English. Next press the left button at the bottom of the screen. It should now look like this:


And this is what the main screen should have looked like:


And there you have it. Set the hotspot name and password you want and you have a WiFi gateway for your beaglebone IoT, which is the subject of a later post, so do check in here again.

Happy trails.

Sunday, 23 July 2017

Klang Valley MRT Opens, a Project Ends


Page 3 of the Sin Chew

17 July 2017 was opening day, and it was supposed to be a doddle. We had finished a month ahead of schedule; but then they ordered 4 more escalators at the last minute.

The fastest way to get around was to use the MRT itself. On opening day I finished up at Station 5 and was expecting to take the train to Station 26 but there was a snag: the trains did not run all the way from Stations 5 to 34. The new segment only went from 16 (Museum Negara) to 34 (Kajang).

Station 5

So at opening time 16:00 hours I was at  Museum Negara and went through as fast as I could. A reporter took a picture as I went through and the next day, it made page 3 of the local Chinese paper, the Sin Chew Jit Poh. 

Post Project Blues

Project C1313K started in 2013 and required remote control of over 200 escalators over 34 stations spanning an area of over 50km. The feature did not exist so it would have to be designed, built and tested on the fly. 
Senior R&D Engineer Edward Boo at ease

For the last 2 years we ate, slept and dreamed C1313K. There were setbacks, attrition, additional requirements, variation orders, but these are teething pains. You focus: eyes on the prize...

The team in 2015


You get used to being occupied by a design for years. Then it is over. OK, it succeeded, it works and is delivered on time and we get to fight another day. There is the high, the celebration, the adrenaline rush.  

Northern Zone passed Field Tests Oct 2016
Southern Zone passed field tests May 2017


So where do you go from there? It is strange not to think about C1313K when you get up or just before you go to sleep. Welcome to the Post Project Blues.

 

Reprieve

 And then you get days like these, 18 July 2017 when you make page 3 of a national paper. Did I say life was good?

Moving On

Time for MRT2 (KVMRT SSP Line) then. Goodbye, C1313K.

But with the word the time will bring on summer,
When briers shall have leaves as well as thorns,
And be as sweet as sharp. We must away;
Our wagon is prepared, and time revives us:
All's well that ends well; still the fine's the crown;
Whate'er the course, the end is the renown.
- William Shakespeare


Sunday, 16 July 2017

Webserver Follies

In the winter of 1996 my friend and former boss Wiljan Derks introduced me to Linux. By the following spring I picked up a Walnut Creek Slackware 1.0 CDROM and installed it from a stack of some 13 3.5" floppy disks. My desktop was a 33MHz Zeos 80486DX souped up to a giddy 66MHz with an 80486DX2 CPU



I had a website, running at tripod, back then one of the first sites to offer free webhosting. Next was a Malaysian pay webhosting site costing some RM300 a year, which proved short-lived. After the site raised its charges by a few hundred percent, and with 3 years of Linux under my belt I hosted the website at home on my trusty Zeos over a 512Kbps broadband line. It was a joy- Linux was a natural fit as a webserver, and without needing to share the server with other websites, performance jumped.

From 1998, home was on top of a little hill in Seremban, which seemed to be a magnet for lightning.No way a little bit of natural static electricity was going to stop me, right? For 20 years I fought the good fight. First I just repaired the procession of stricken modems, routers, network hubs, desktops and  implacably put them back on line. Then I realized that the lightning caused so many power outages I needed an uninterruptible power supply.

The UPS solved the power outage problem, but made the lightning problem worse. With the web server running through the storm the lightning strokes frequently ran through the telephone landline into my power grid Earth, often passing through the surge arrestors in the modem. This made for a lot of dead modems. Sometimes the strikes hit the lamp or telephone post in my compound(don't even talk to me about the gatepost lights) and even damaged monitors, network switches and network cards.

WiFi brought some hope - there is now no direct link between the server and the modem. True, modems still died at the usual rate of some 4 or 5 a year but the server was usually fine. This meant the UPS had to be up-sized especially if the storm occurred on a weekend and we were not at home to reset the mains breaker. Even with an out-sized UPS, the battery replacement costs were roughtly RM800 over 2 years. It made more sense to downsize the server to the ARM-based beaglebone. The Raspberry Pi seemed even better, but try as I might it would not run WiFi reliably.      

 Currently the web server runs on a Beaglebone original, a 720MHz 256MB ARM Cortex-M3 (Zeos was 66MHz 16MB and used bucketloads of power), hacked to run Slackware. A WiFi modem supplies 4MBps bandwidth (512Kbps uplink) and the hacked APC Matrix 3000 can pretty much power the setup for a week, but Fate intervened.




After so many years, the wife have had enough of the lightning strikes taking out the modems and interrupting her Facebook sessions. She had taken to disconnecting the telephone line from the modem before the storms which saves the modems but do not do much for server uptime.

So it is time for paid webhosts again. I signed up for Amazon's AWS and after a full year's free trial it is time to move the website, this time to AWS with docker and Wordpress, the latter to to sex up the 20-year old website a little.

About time, don't you think?

Saturday, 1 July 2017

The "TWO Groups" Section Switch and the Internet of Things

The wife bought a fancy lamp for the gatepost which changes color when the power switch is flipped off and on quickly. I got a chance to look at it when it got damaged by a nearby lightning bolt. It turned out there were two LED lamps inside, one white and the other yellow. An electronic module switches one or the other or both based on the number of times you flipped the power off and on.


Now this is a great way of powering an Internet of Things remote device on the cheap. Say you want to install a WiFi camera and you want to be able to switch it on together with a nearby lamp (for night use), or to turn on just the camera without the lamp, or just turn the light on without turning on the camera. You install this Section Switch so that it powers both the lamp and the camera.

I dismantled the gatepost lamp, and the wife took it back to the shop where she bought it, where she had it repaired for RM20 (less than USD5). The shop replaced the section switch, and returned the defective section switch as proof of repair. You can buy it online (or at your friendly lighting shop) for RM18.

Warning - do not attempt this yourself unless you have had specialist training in switch-mode power supplies. There are lethal voltages in this module.

I thought I would fix the Section Switch just to see how it worked. It is easily opened- just press firmly at the base of the long side of the module and the base plate pops out.



The lights are switched by two 12V relays controlled by an integrated circuit, the JY2608. I am afraid the datasheet is in Mandarin, but don't let that stop you. The original website is a bit spotty- if you cannot get the datasheet place a comment here and I'll email you my copy.

The datasheet has a sample circuit for the JY2608 and it looked like the manufacturer has copied it lock stock and barrel. Here is the sample circuit from the datasheet:



Now the problem with the Section Switch was when switched, the lights took a very long time (sometimes hours) to come on. So we know the problem is related to the power section.

I powered up the defective module with this setup:


Note the use of an isolation transformer (the box with the white power dial) and and a portable ELCB for safety. The Section Switch has no transformer, so the semiconductors are connected directly to the mains power - in this case 230Vac. Some types of faults can cause the module to explode or catch fire if connected directly. Here, the isolation transformer limits the mains power to less than 20W. An isolation transformer can break the Earth connection to your house ELCB, so use an extra ELCB to protect yourself.

I have also secured the wires to a strip of screw terminals for extra safety.

OK, back to the input power problem. I measured the input power to the IC (the JY2608 is a 12V device) at D1 the 12V zener diode's anode and it read 5.8V. That is very far from the 12V it needs. Actually the JY2608 will work at 2V but the relays need at least 9V to switch.

I replaced the 12V zener with an 1N4742A and powered on, but the voltage stayed at 5.8V. So it is not the zener diode but something closer to the input power.

A closer look at the circuit showed that the bridge rectifier (four diodes in the shape of a diamond) is powered by C1 and R1 in parallel, a 1.5uF capacitor and 330KOhm resistor. I tested the resistor using the multimeter (the black and orange thing in the foreground) and it reads correctly at 330K.

Next I replaced the capacitor with a 1uF capacitor I had handy, and now the Section Switch powers up nicely at 12V and the relays clicked when I flipped the mains power off then on. 230V appeared on both outputs so the repair is done.

Now the repair costs some RM3 for the 1uF 400V film capacitor, and it only cost RM18 to buy, not to mention the hazards involved. But that is a little bit of electronics saved from the scrap heap.

The next step would be to hook it up to power an IoT device, so stay tuned!

[2021-05-01 Update] The section switch in the other gatepost failed: when the main lamp is turned on it started flashing, with the section switch clicking away briskly on its own. A diode (D4) in the mains bridge rectifier was shorting. Replaced that with a 1N4007 and it worked like before. In all fairness it is fairly reliable despite its cheap price. My gatepost lamps are exposed to the elements; alternately wet from driving rain and hot from the greenhouse effect of the glass lamp housing. Myriad bugs occasionally lived (and died) there.