Santa Light – What’s Inside

During the Christmas season I found a Santa light at the local Dollar Tree store. Knowing that it is just a garden light with a Santa head, I bought one just to experiment with. OK – I’m a little obsessed with these garden lights – BUT – that IS how this blog started. One of my earliest posts was about a garden light.

Every garden light that I examine has something unique about it. Santa’s electronics had differences. First, the ASIC chip is a new one to me. I cannot find a specification sheet for it but, based on haw it is wired, it is similar to the YX805A. It is marked “F1 4S597”. The other unique thing is the battery. It is a small “2/3AAA” NiCd 100mAh battery. Every other light that I’ve encountered uses a AAA NiCd/NiMH battery. Other than this and the shape of the housing there is nothing unusual in the design.

Disassembly and oscilloscope photos are below, as well as my reverse engineered schematic. (Click photo to enlarge) Enjoy!


Posted in Electronics, hardware | Leave a comment

Garden Light Redux – Power Supply

NOTE: This post is a work in progress. As long as it ends with “To be Continued”, please check back occasionally for updates.

The Garden Solar Light is a recurring interest of mine. It is often referred to as a Joule Thief but it is actually not.  A Joule Thief attempts to extract usable power from an almost dead battery ( under 0.8 volts) while this technology is a switch pulsed voltage boost converter that operate above 0.9V.  The somewhat mysterious little Chinese ASIC integrated circuits have been examined by a number of people since I first posted about the subject in 2012. Recently, a fellow member of the Asheville based Western North Carolina Linux Group (WNCLUG) re-sparked my interest in the topic. Our ultimate goal is a modified Garden Light that can power an ATTiny85, radio transmitter and sensor for periodic transmission of sensor data.

This time I decided to spend some time delving more into the somewhat mysterious little Chinese integrated circuits used in the solar garden lights so as to, hopefully, make more informed design decisions in the final project. There is a plethora of similar Chinese Garden Light integrated circuits and, despite having different identifying part numbers, they seem to all be similar of each other, despite some variation in pin assignments and capabilities.

A pretty good list of them is HERE. Despite their similarities, one reason for the overabundance choices, besides competition between manufacturers, is to accommodate for different current and voltage applications as well as other improvements, such as over discharge protection. Some of the improvements are patented.  I found an interesting list of Garden Light ASICs on in a post by user yuxinzxs. See the English translation of the Garden Light portion at garden-light-asic-list The YX8018 appears to be the granddaddy of them all. The YX8018 and the QX5252F seem to be the most commonly encountered. The QX5252F is manufactured by QX Micro Devices Co., LTD of Shenzhen, China who holds several patents for these types of chips that prevents the battery from being overly discharged in order to prolong battery life – Chinese patents 200910107832 and 200910107063 and 200910107064 for high efficiency charging.

By the way, before I start ignoring the YX8018 in favor of the QX5252F, if the YX8018 interests you check out SparkFun’s interesting project for creating a soil moisture sensor using a Garden Stake that uses the YX8018. It is simple but informative. If the soil is damp, the LED is out. If the soil is dry, the LED is lit. Read the SparkFun article at THIS-LINK.

The YX8018, like most of its cousins, come in 4 pin transistor SIP-4 package identified as TO-94, which can be seen in Figure 1, below. The internal schematic of these Chinese voltage booster chips is elusive. However, there are a few semi-schematics of the internals, one of which was posted in an Instructable by Dave Kruschke and it appears a little more complete than others that I have discovered – However, the slightly simpler internal schematic posted by burger2227 (Ted from Pittsburgh) is quite adequate and is shown immediately below in Fig. 1.


Fig. 1: YX805A

Below is a somewhat more detailed internal view from a manufacturer datasheet.


Fig 1a: QX5252F Functional Block Diagram

The integrated Shottkey diode between the solar panel on pin SBAT and the battery on pin BAT is part of the charging circuit and also blocks the battery from biasing on the controller/oscillator (white box in center). The gated oscillator runs at a ~200KHz driving an open drain NMOS switch ( output on pin LX ). The non-sinusoidal pulses on LX pin pulse the external inductor (Figure 2) at the ~200kHz rate and the resultant field collapses boot the voltage presented to the LED in the manner of a Joule Thief. The Instructable by Dave Kruschke has a nice explanation of how the inductor creates the voltage boost. Each pulse causes current to flow into the inductor which creates a magnetic field around the inductor, that is, in essence, stored energy. When the pulse ends, current flow stops, the inductor’s magnetic field collapses and its energy is returned back into the circuit, adding to, or “boosting” the voltage.


Voltage Boost via Coil Field Collapse

I purchased some YX805A chips through eBay and, as the first step, I am replicating a Garden Light’s circuitry on a breadboard. I configured the basic circuit in Figure 2, below, except for the solar charging portion. For now I am only testing the voltage booster section with an alkaline 1.57V. battery.


Fig. 2: Initial Test Circuit

My initial breadboard test circuit is shown in Figure 3, below.

Fig. 3

I used a YX805A chip with a 100uH inductor and a white LED. The battery used was a AA size alkaline battery that measured 1.57V with a voltmeter. This configuration oscillates at 215kHz. See Fig. 3, below. Most white LEDs require 3-Volts to conduct/illuminate, and typically operate in the 3.2V to 3.4V range. The output measured 3.6V between ground and LX, the pulsed output. At this point the 215kHz is only usable for the LED light application, where the human eye cannot detect the oscillation. Rectification and stabilization will be needed before the output is usable for anything else.

Fig. 4 – YX805A with Alkaline Battery

With a 1.29V NiMh battery the oscillation frequency was slightly different, at 226kHz, see Figure 5, below. However, the oscillator isn’t that stable so both the alkaline and NiMh batteries produced the expected approximate 200kHz frequency.

Fig. 5: nimh battery 100u

Fig. 5: YX805A with NiMH battery 100uH inductor

With the same circuit but using a 5252F ASIC instead of the YX805A. Results are very similar as can bee seen in Figure 6, below. The frequency was somewhat higher at 282kHz and the waveform even less of a square wave than with the YX805A. Nonetheless, quite similar and equally usable.


Fig. 6: 5252F, 100uH, 1.25V NiMh

My next incremental step was to rectify and stabilize the circuit’s output to 5 volts. At this point I have not installed the solar cell charger – that will come later.

The schematic shown in Figure 7, below, provides 5.18VDC across a megohm load (multimeter), at 45ma  (only multimeter’s load in Ampere mode) from a fully charged 1.29V NiMH battery. With a 33uH inductor it supplies 50ma. These readings match the YX805A datasheet in that the smaller inductor value does produce more current (290kHz) but the values differ from the chart. Possibly this is due to my using a signal diode instead of the datasheet’s white LED, or it is due to the particular manufacturer of my YX805A.

When measured across, and through, a sustained 19Ω load, meaning starting from a discharged capacitor, I see 5.1VDC at 580uA. Conversely, if the capacitor is fully charged prior to applying the load, I measure 5.1V @ 25ma. This test was using a 33uH inductor. When measured across, and through, a 1kΩ load with a charged capacitor I see 5.1VDC at 5.1mA. A subsequent test, with the circuit moved to a new breadboard and using a 22uF filter capacitor yielded ~17mA through a dead short (ammeter).

To be usable as a power supply, the load may need to be intermittent in order to charge the capacitor between higher current cycles. Fortunately, Dolen Le has researched and documented exactly how to do this with the ATTiny85.

The solar charging portion is not part of the initial tests. Without the 5.1V zener the output voltage is 8.5V.


Fig. 7: Basic 5V Supply Added

Using the oscilloscope I measured the 5V ripple at .05V – time to see what it can do!
I programmed an Arduino NANO with the one-second Blink program and connected it to be powered by the Garden Light Redux – Power Supply. It worked perfectly (for now) with the 1000uF capacitor providing a current reserve. A short video is below that shows the Arduino running under Joule Thief power from one NiMH AA battery.

UPDATE: Something changed and I can no longer replicate these results with the YX805A circuit described above, meaning that the NANO will no longer run with that power supply. Currently, I am seeing much less current than before and it isn’t enough to operate the Arduino NANO. Trying to see what was happening I put scope leads across the Arduino NANO power leads and then connected the my Garden Light DIY 5V Power Supply. What I see it starting at 5.2V and within 140ms voltage was down to 3V with a precipitous drop after that. See Figure 8, below. I don’t know what changed – I have replaced all components, one at a time between tests, except for the Arduino NANO. Changing the NANO is on my list. Meanwhile, I compared current load with “this” genuine Arduino NANO e/w FTDI serial I/O and a Chinese Arduino NANO e/w CH340G I/O – both running a “blink” program. Idle is the low current and LED-on is the high current:

  • genuine Arduino NANO e/w FTDI serial I/O – current 25-to-30mA
  • Chinese Arduino NANO e/w CH340G I/O – current 22-to25mA
Fig. 8: Voltage drop on NANO Connection

Fig. 8: Voltage drop on NANO Connection

Seeing that this circuit wasn’t going to be adequate to power the Arduino NANO, I did some measurements using the BLINK program in an ATTINY85-20SUR surface mount package – see video below. Idle current consumption is 8.7mA and with the LED on it is 11.5mA. Better, but still a challenge for the ATTiny85 and a transceiver plus sensor. The supply still needs work.

I made some changes and have a working circuit again! I hate the unexplained. Anyway, I switched to a QX5252F ASIC, 100uH inductor and a Schottky diode. See figure 9 below. I’m seeing 5.1V with 125mA on a dead short and 43mA through a 1000Ω resistor. This circuit correctly runs the ATTiny85 running Blink in the video immediately above.


Fig. 9: QX5252F & 100uH inductor


Fig. 10: QX5252F Schematic

I didn’t like the unexpected change in performance, so additional testing is in order before I can say that this circuit is solid. A future step will be to more extensively test the basic solar charging circuitry – I have already briefly tested it. After that, I may add and test Ivan Nechayev’s charge regulation circuitry.

Keep watching this post to expand – it is NOT finished. Other posts may be used will wait for other aspects of my project, such as adding the radio transmitter and sensor. Until then:

To Be Continued

Posted in Electronics, hardware | Tagged , , , , | 2 Comments

An inexpensive Software Enabled Pseudo-Transceiver for Arduino

Recently I taught a brief, three hour long, Arduino 101 course to some fellow members of the Western North Carolina Linux Users Group (WNCLUG). One of the three lessons in the course was for the students to pair off and use inexpensive Chinese 433 megahertz radio modules to send data between an Adruino Uno with a FS1000A transmitter running transmitter code and another Adruino Uno with a MX-RM-5V receiver running receiver code. We talked about applications using a transceiver but these radios were discrete transmitters and receivers, NOT transceivers. Of course that was understandable because this transmitter and receiver set only cost 88 cents (in bulk), including shipping from China via AliExpress.

Cheap ASK Radios

FIG 1: Cheap ASK Radios

Recently, I got to thinking – it seemed to me that I could use the two boards (FS1000A & MX-RM-5V) with a single Arduino to create an 88-cent transceiver through software. Consequently, I wrote some code that does just that is explained herein.

With the two radio modules in close proximity of the single controlling Arduino, such as on the same breadboard, I was concerned about the transmitter swamping the companion receiver during transmit, and possibly producing spurious results in the receiver. I decided to use the oft recommended RadioHead Arduino ASK library for this project. It can be downloaded from its author –

RadioHead has a useful Push To Talk (PTT) feature that I opted to use to control receiver’s power. The PTT feature is intended to control a genuine transceiver but I use it to toggle on/off the power for the MX-RM-5V receiver. I invert the pin in software such that power is removed from the receiver when the transmitter is keyed. The receiver MX-RM-5v Working current at 5V is a nominal 4ma and the Arduino can source DC Current per I/O Pin at 40.0 mA, so powering the receiver via an Arduino works without issue.

I cobbled together a simple test of the software with two breadboards (see Fig 2). The serial ports were each monitored on my desktop and a laptop. Fig 3, below shows two-way messaging between the two pseudo transceivers.

Two pseudo Transceivers

Fig 2: Two pseudo Transceivers

While I have tested these cheap ASK radios at over 50 feet, I have read reports by others that they will work much, much further. These particular radios are test rejects from a bulk order made for my class and they won’t work much further than a foot apart. Someday I may try to tune the suspect receiver.

Test Results

Fig 3: Test Results – two screens

Below, in Fig 4, I show the wiring for my tests – both breadboards are wired identically and run the same code.

Pseudo Transceiver Wiring

Fig 4: Pseudo Transceiver Wiring

UPDATE: January 30, 2017 – I tested a different, higher rated radio with the exact setup and code, EXCEPT that I only tested one-way communications – because I was testing the radios, not the code. I tested the STX882 / SRX882 radio pair shown in Figure 5, below, and they worked well. Ok, not these two because I haven’t soldered the antennas onto these yet – it was another pair. I did not test maximum range but they worked across the table – see Figure 6, below. Their manufacturer, NiceRF, claims an effective range of 100 meters.


Fig 5: STX882 and SRX882


Fig 6: Test Communications with STX882 and SRX882


The source code can be downloaded from: and is also shown below. NOTE: Source code updated on December 26, 2016.

  ask_rxtx.ino - V2
  AUTHOR: Edward Comer, USA
  Open Source Licenesed under Creative Commons Attribution 4.0 International (CC BY 4.0)
  Uses RadioHead library for messaging via a simple ASK transmitter and
  receiver, i.e., FS1000A and MX-RM-5V, etc.

  For RadioHead information, see:
  Controls both transmitter AND receiver
  Receiver is powered by inverted PTTPIN, which powers down receiver when
  transmitting in order to prevent swamping the receiver.
  Receiver MX-RM-5v Working current:≤5.5mA (5.0VDC) nominally 4ma
  Arduino DC Current per I/O Pin: 40.0 mA

   +-------+   +---------+
   |FS1000A|   |XD-RF-5V |
   |D 5 G  |   | 5 D  G  |
   ++-+-+--+   +-+-+--+--+
    | | |        | |  |
    | + +        | |  +
    |            | |
  | 1            1 1  |
  | 2            0 1  |
  |    ARDUINO        |

#include <RH_ASK.h>
#include <stdint.h>
#include <SPI.h> 	// Not actually used but needed to compile

#define SPEED 2000  // The desired bit rate in bits per second
#define RXPIN 11    // The pin that is used to get data from the receiver
#define TXPIN 12    // The pin that is used to send data to the transmitter
#define PTTPIN 10   // Push To Talk pin
#define PTTINVERTED true // true = LOW when transmitting, otherwise HIGH


char kbdbuf[RH_ASK_MAX_MESSAGE_LEN];
uint8_t rxbuflen = sizeof(rxbuf);

const int ledPin = 13; // onboard LED

void setup()
  digitalWrite(ledPin, HIGH);
  while (!Serial); // Wait for serial connect
  if (!driver.init())
    Serial.println("Radiohead driver.init failed - system halting");
    while (true) {}  // do nothing further until reset
  digitalWrite(ledPin, LOW);
  Serial.print("Maximum message length requested of this Driver is ");
  Serial.print("Maximum message length available in this Driver is ");
  Serial.println("Setup complete.");
  Serial.println("Enter New message: ");

   loop, contstantly checking for either a string to transmit or
   a received string. This loop is predominantly non-blocking. The receiver
   is powered down when the transmitter is sending to prevent swamping the
   receiver. Power down/up is accomplished by powering the receiver with
   the RadioHead PTT pin (pin 10). The receiver uses 5V @ 4ma and the
   Arduino can source 40ma.

   NOTE: There is no immediate local echo of characters typed
void loop()
  if (readline(, kbdbuf, RH_ASK_MAX_MESSAGE_LEN) > 0)
    Serial.print("You entered: [");
    // Now, Send user typed string via radio
    driver.send(kbdbuf, strlen(kbdbuf));
    Serial.println("Transmit complete");
    delay(500);  // settling time for RX turnon

  // Check for data received via radio
  if (driver.recv(rxbuf, &rxbuflen)) // Non-blocking
    // Message with a good checksum received, dump it.
    //driver.printBuffer("Received:", buf, QtyRead);
    Serial.write(0x07); // Ring bell on Putty console
    Serial.print("Received: ");
    rxbuflen = sizeof(rxbuf);
    Serial.println("Enter New message: ");

   Non-blocking string read from terminal
   name: readline(int readchar, char* buffer, int len)
   @param readchar is the character read
   @param buffer is storage for accumulated string
   @param len is maximum length input string allowed
   @return returns length of string read, otherwise negative value

   Inspired by Majenko's Hardware Hacking Blog
int readline(int readchar, char* buffer, int len)
  static int pos = 0;
  int ret_pos;

  if (readchar > 0) {
    switch (readchar) {
      case '\r': // Terminate with CR or LF
      case '\n':
        ret_pos = pos;
        pos = 0; // Reset position index ready for next entry
        return ret_pos;
        if (pos < len - 1) {
          buffer[pos++] = readchar;
          buffer[pos] = 0;
        } else {	// else buffer is full
          buffer[pos] = 0;
          ret_pos = pos;
          pos = 0; // Reset position index ready for next entry
          return ret_pos;
  // No end of line has been found, so return -1.
  return -1;

Posted in Arduino, Electronics, Programming, software, wireless | Tagged , , , | Leave a comment

Programming the ATTINY85-20SUR

This post ties together my two previous posts, “ATtiny85 SOIC chip Program Adapter” and “Universal programmer dusted off“. I inserted the ATTINY85-20SUR nested in the SOIC Adapter Socket OTS-20-1.27-01,  plugged it into my DIY Universal Programmer socket and connected it up to my USBasp programmer. I first burned the bootloader and then burned a typical “blink” program. Next, I plugged the ATTINY85-20SUR/ SOIC Adapter Socket into a small breadboard that I have for a Arduino Uno ProtoShield (it was my only empty breadboard) and connected 3.3V power from a handy breadboard power supply.

Everything worked nicely so I can now move on to the next phase of a long-running project that I’m working on. I’ve put a small video below that will give you a visual context of what I did.

Posted in Arduino, Electronics, hardware | Tagged , , | Leave a comment

ATtiny85 SOIC chip Program Adapter

When I purchased some surface mount ATtiny85 microcontrollers I didn’t realize that Atmel sold them in several widths, so I purchased the incorrect size SOIC programming adapter that would have enabled me to program the chip prior to soldering it onto the PCB. I had purchased ATTINY85-20SUR chips which use Atmel’s package type “8S2”. Using a micrometer, I measured the pin widths on a ATTINY85-20SUR and it measures 7.87mm, which is within the range specified by Atmel – 7.62mm to 8.38mm wide pin edge to pin edge.

So, back to eBay I go and I purchased a SOIC Adapter Socket OTS-20-1.27-01 mounted on a small PCB and sold as a SOIC Programmer Adapter Socket compatible with 200/208mil SOIC, 1.27mm Pitch. The PCB is wired to facilitate programming on a breadboard. Wiring is pin to pin, thus SOIC pin 1 goes to PCB pin1, etc. See Figure 1, below.

SOIC Socket From eBay

Figure 1: SOIC Socket From eBay

Figure 2, below, illustrates the ATmel specifications for the ATTINY85-20SUR chip and what I actually measured.


atmel SOIC spec

Figure 2: ATmel 8S2 SOIC spec

The very short video clip, below, demonstrates how easy it is to insert/remove a 8S2 SOIC chip in the SOIC Adapter Socket OTS-20-1.27-01.


Posted in Arduino, Electronics, hardware | 1 Comment

Universal programmer dusted off

Lately, I have increased my microprocessor/gadget activity after a hiatus/slow down. A project that I have been (slowly) working on was developed and debugged on an Arduino NANO but the final target is a surface mounted SOIC ATtiny85-20SUR operating at 3-Volts. On an interim basis, I am testing with 8-DIP ATtiny85-20 chips. I have been programming the ATtiny85-20 chips with a USBasp programmer and a perf-board adapter that I made back in 2012.  The perf-board adapter is shown in Figure 1, below.

In the same storage box as the perf-board adapter was a universal adapter that I also made in 2012. I needed it for some other, larger chips that I was programming, at the time. It has a 48-pin Zero Insertion Force socket (ZIF 250-3345).

The USBasp programmer in the photo is another story. I have two of these inexpensive Chinese programmers. I purchased the first one in 2012 and I liked it so much that I bought a second one as a maintenance spare. In the years that have passed I have changed my desktop workstation operating two or three times. I am now on Mint 17.3. Something in Linux has changed because this USBasp programmer originally created a /dev/ttyUSB0 port but – no longer! I tried every udev rule offered by the Internet pundits but nothing would work. I have the programmer working on /dev/ttyS0 but it bugs me that Linux’s behavior has changed. Since my two USBasp devices are Chinese-made and several years old, I suspect that their FTDI chips are probably counterfiet. I am growing suspicious that FTDI may have inserted some form of their malicious code into Linux. It is widely publicized about what they did to Linux drivers ( Seeing that FTDI supplies the Linux kernel’s USB drivers, I went looking for the source to see what I could find out. Guess what – FTDI’s driver ReadMe file states “FTDI do not release the source code for libftd2xx. If you prefer to work with source code and are starting a project from scratch, consider using the open-source libFTDI.” Sure enough, Linux is using FTDI supplied compiled objects into the kernel. Oh well, I guess I’ll stick to using /dev/ttyS0.

Universal Programmer

Figure 1. – Universal Programmer

My DIY universal programmer adapter was made on a quickie, somewhat crude one-sided printed circuit board. I was making quite a few PC boards in 2012/3. The artwork and schematic for this board is at the bottom of this post.

Universal Programmer Board

Figure 2. – Universal Programmer Board TOP

Universal Programmer Board

Figure 3. – Universal Programmer Board BACK (ignore felt pen incorrect legend)

I just setup the Universal Programmer board and burned a ATtiny85-20 fused to run at 8MHz. I’m glad that the universal adapter still works well. The console output below is just a “blink” program to test the programmer. I have already tested my project’s code in a 3.3-volt adafruit trinket so I know that it is going to work well inside an ATtiny85.

ecomer@bergamont ~/Arduino/BlinkATTiny85 $ make upload
------------------------- Configuration:
- [USER]               ARDUINO_DIR = /home/ecomer/arduino-1.6.9 
- [USER]               ARDMK_DIR = /home/ecomer/Arduino/Arduino-Makefile 
- [DEFAULT]            ARCHITECTURE = avr 
- [DEFAULT]            ARDMK_VENDOR = arduino 
- [AUTODETECTED]       ARDUINO_PREFERENCES_PATH = /home/ecomer/.arduino15/preferences.txt 
- [AUTODETECTED]       ARDUINO_SKETCHBOOK = /home/ecomer/Arduino (from arduino preferences file)
- [USER]               AVR_TOOLS_DIR = /home/ecomer/arduino-1.6.9/hardware/tools/avr 
- [COMPUTED]           ARDUINO_LIB_PATH = /home/ecomer/arduino-1.6.9/libraries (from ARDUINO_DIR)
- [COMPUTED]           ARDUINO_PLATFORM_LIB_PATH = /home/ecomer/arduino-1.6.9/hardware/arduino/avr/libraries (from ARDUINO_DIR)
- [USER]               ALTERNATE_CORE = tiny 
- [COMPUTED]           ALTERNATE_CORE_PATH = /home/ecomer/Arduino/hardware/tiny/avr  (from ARDUINO_SKETCHBOOK and ALTERNATE_CORE)
- [COMPUTED]           BOARDS_TXT = /home/ecomer/Arduino/hardware/tiny/avr/boards.txt (from ALTERNATE_CORE_PATH)
- [USER]               USER_LIB_PATH = /home/ecomer/Arduino/lib 
- [DEFAULT]            PRE_BUILD_HOOK = 
- [USER]               BOARD_TAG = attiny85at8 
- [COMPUTED]           CORE = tiny (from build.core)
- [COMPUTED]           VARIANT =  (from build.variant)
- [USER]               OBJDIR = /home/ecomer/Arduino/BlinkATTiny85/attiny85at8/bin 
- [USER]               ARDUINO_CORE_PATH = /home/ecomer/Arduino/hardware/tiny/avr/cores/tiny 
- [USER]               MONITOR_BAUDRATE = 115200 
- [DEFAULT]            MCU_FLAG_NAME = mmcu 
- [USER]               CFLAGS_STD = -std=gnu11 
- [USER]               CXXFLAGS_STD = -std=gnu++11 
- [COMPUTED]           DEVICE_PATH = /dev/ttyS0 (from MONITOR_PORT)
- [AUTODETECTED]       Size utility: AVR-aware for enhanced output
- [COMPUTED]           BOOTLOADER_PARENT = /home/ecomer/arduino-1.6.9/hardware/arduino/avr/bootloaders (from ARDUINO_DIR)
- [COMPUTED]           ARDMK_VERSION = 1.5 
- [COMPUTED]           CC_VERSION = 4.8.1 (avr-gcc)
mkdir -p /home/ecomer/Arduino/BlinkATTiny85/attiny85at8/bin
make reset
make[1]: Entering directory `/home/ecomer/Arduino/BlinkATTiny85'
/home/ecomer/Arduino/Arduino-Makefile/bin/ard-reset-arduino  /dev/ttyS0
make[1]: Leaving directory `/home/ecomer/Arduino/BlinkATTiny85'
make do_upload
make[1]: Entering directory `/home/ecomer/Arduino/BlinkATTiny85'
/usr/bin/avrdude -q -V -p attiny85 -C /home/ecomer/arduino-1.6.9/hardware/tools/avr/etc/avrdude.conf -D -c usbasp -b 9600 -P /dev/ttyS0 \
			-U flash:w:/home/ecomer/Arduino/BlinkATTiny85/attiny85at8/bin/BlinkATTiny85.hex:i

avrdude: warning: cannot set sck period. please check for usbasp firmware update.
avrdude: AVR device initialized and ready to accept instructions
avrdude: Device signature = 0x1e930b
avrdude: reading input file "/home/ecomer/Arduino/BlinkATTiny85/attiny85at8/bin/BlinkATTiny85.hex"
avrdude: writing flash (714 bytes):
avrdude: 714 bytes of flash written

avrdude: safemode: Fuses OK (H:FF, E:D7, L:E2)

avrdude done.  Thank you.

As you can see, I have also been fiddling with Make for Arduino compiling and burning. This particular Makefile is by Sudar Muthu of Chennai, India. You can download it at I gravitated to this Makefile because some of my semi-anonymous work is within. Sudar built upon Christopher Peplin’s previous work and I am a contributor to Peplin’s now depricated makefile. Consequentially, I knew this particular Makefile well. Nonetheless, things have changed since 2012. The format of “boards.txt”, a critical Arduino parameter file, has dramatically changed since 2012. Arduino has added a new structured “menu” version of “boards.txt” that can be very difficult to parse with a Makefile, especially since has no published standard. Due to this, each Arduino “core” developer invented “tags” in “boards.txt” that are unique to their “core”. I frustratingly tested several and gave up and settled on the ONE that worked well. It is arduino-tine version 0150-0020in the Google code repository at Can I do what I need in the Arduino IDE? – Sure but I am a hands-on guy and the goal of the Arduino ide is to insulate the developer from what is happening. I don’t like that and usually pick the hands-on approach even if it isn’t always as easy.

zifboard1s schematic

Figure 4. – ZIF Universal Programmer Adapter Schematic

ZIF Universal Programmer Adapter Art

Figure 5. – ZIF Universal Programmer Adapter Single Sided Art

Posted in Arduino, computer, Electronics, hardware, Linux, PCB Etching, Programming | Leave a comment

Dubious eBay SD Cards – Caveat Emptor

Over the years, I have purchased a number of SD cards through eBay – often shipped directly from China. Today I was reading the setup instructions for a recent acquisition – a PINE-64 board. Pine-64 was adamant that the micro-SD card used be over 8GB and of Class 10. I dug around on the shelf and came up with a spare 32GB micro-SD. It was marked as Class-4. No good for this application BUT I got to wondering how it would test. A photo of the SD card’s markins is below, front and back.

I had recently discovered a suite of SD testing tools called F3 by Michel Machado. I downloaded the source and compiled the suite. Next, I ran the tools against the SD card. The results were BAD! The card is a fake and only has 7GB usable. The console’s output is pasted below. The reported average writing speed is 3.07 MB/s, which would be between a Class 2 and Class 4. The card is marked Class 4 so the speed is also a fake. I’ve learned my lesson – no more direct-from-China SD cards unless I can truly trust the seller – which seems pretty difficult on eBay. Consequentially, I think that I will stick to companies with good return policies (Amazon, NewEgg and Wal-Mart) and immediately test the new card with F3. Caveat Emptor!

dzrmo@bergamont ~/src/f3-6.0 $ ./f3write /media/dzrmo/9C6F-1ECD
Free space: 29.80 GB
Creating file 1.h2w ... OK!
Creating file 2.h2w ... OK!
Creating file 3.h2w ... OK!
Creating file 4.h2w ... OK!
Creating file 5.h2w ... OK!
Creating file 6.h2w ... OK!
Creating file 7.h2w ... OK!
Creating file 8.h2w ... OK!
Creating file 9.h2w ... OK!
Creating file 10.h2w ... OK!
Creating file 11.h2w ... OK!
Creating file 12.h2w ... OK!
Creating file 13.h2w ... OK!
Creating file 14.h2w ... OK!
Creating file 15.h2w ... OK!
Creating file 16.h2w ... OK!
Creating file 17.h2w ... OK!
Creating file 18.h2w ... OK!
Creating file 19.h2w ... OK!
Creating file 20.h2w ... OK!
Creating file 21.h2w ... OK!
Creating file 22.h2w ... OK!
Creating file 23.h2w ... OK!
Creating file 24.h2w ... OK!
Creating file 25.h2w ... OK!
Creating file 26.h2w ... OK!
Creating file 27.h2w ... OK!
Creating file 28.h2w ... OK!
Creating file 29.h2w ... OK!
Creating file 30.h2w ... OK!
Free space: 0.00 Byte
Average writing speed: 3.07 MB/s
dzrmo@bergamont ~/src/f3-6.0 $ 

dzrmo@bergamont ~/src/f3-6.0 $ ./f3read /media/dzrmo/9C6F-1ECD
                  SECTORS      ok/corrupted/changed/overwritten
Validating file 1.h2w ... 2097152/        0/      0/      0
Validating file 2.h2w ... 2097152/        0/      0/      0
Validating file 3.h2w ... 2097140/        0/     12/      0
Validating file 4.h2w ... 2097151/        0/      1/      0
Validating file 5.h2w ... 2097152/        0/      0/      0
Validating file 6.h2w ... 2097152/        0/      0/      0
Validating file 7.h2w ... 2097152/        0/      0/      0
Validating file 8.h2w ...  678512/        8/      0/1418632
Validating file 9.h2w ...       0/        0/      0/2097152
Validating file 10.h2w ...       0/        0/      0/2097152
Validating file 11.h2w ...       0/        0/      0/2097152
Validating file 12.h2w ...       0/        0/      0/2097152
Validating file 13.h2w ...       0/        0/      0/2097152
Validating file 14.h2w ...       0/        0/      0/2097152
Validating file 15.h2w ...       0/        0/      0/2097152
Validating file 16.h2w ...       0/        0/      0/2097152
Validating file 17.h2w ...       0/        0/      0/2097152
Validating file 18.h2w ...       0/        0/      0/2097152
Validating file 19.h2w ...       0/        0/      0/2097152
Validating file 20.h2w ...       0/        0/      0/2097152
Validating file 21.h2w ...       0/        0/      0/2097152
Validating file 22.h2w ...       0/        0/      0/2097152
Validating file 23.h2w ...       0/        0/      0/2097152
Validating file 24.h2w ...       0/        0/      0/2097152
Validating file 25.h2w ...       0/        0/      0/2097152
Validating file 26.h2w ...       0/        0/      0/2097152
Validating file 27.h2w ...       0/        0/      0/2097152
Validating file 28.h2w ...       0/        0/      0/2097152
Validating file 29.h2w ...       0/        0/      0/2097152
Validating file 30.h2w ...    8256/        0/      0/1661312

  Data OK: 7.33 GB (15366819 sectors)
Data LOST: 22.47 GB (47120157 sectors)
	       Corrupted: 4.00 KB (8 sectors)
	Slightly changed: 6.50 KB (13 sectors)
	     Overwritten: 22.47 GB (47120136 sectors)
Average reading speed: 13.77 MB/s

dzrmo@bergamont ~/src/f3-6.0 $ sudo ./f3probe --destructive --time-ops /dev/sdf
[sudo] password for dzrmo:
F3 probe 6.0
Copyright (C) 2010 Digirati Internet LTDA.
This is free software; see the source for copying conditions.

WARNING: Probing normally takes from a few seconds to 15 minutes, but
         it can take longer. Please be patient.

Bad news: The device `/dev/sdf' is a counterfeit of type limbo

You can &amp;quot;fix&amp;quot; this device using the following command:
f3fix --last-sec=15466495 /dev/sdf

Device geometry:
	         *Usable* size: 7.38 GB (15466496 blocks)
	        Announced size: 30.00 GB (62914560 blocks)
	                Module: 32.00 GB (2^35 Bytes)
	Approximate cache size: 3.88 MB (7952 blocks), need-reset=yes
	   Physical block size: 512.00 Byte (2^9 Bytes)

Probe time: 2'15&amp;quot;
 Operation: total time / count = avg time
      Read: 1.39s / 32937 = 42us
     Write: 2'09&amp;quot; / 125776 = 1.0ms
     Reset: 4.05s / 16 = 253.2ms
dzrmo@bergamont ~/src/f3-6.0 $ 

dzrmo@bergamont ~/src/f3-6.0 $ sudo ./f3fix --last-sec=15466495 /dev/sdf
F3 fix 6.0
Copyright (C) 2010 Digirati Internet LTDA.
This is free software; see the source for copying conditions.

Drive `/dev/sdf' was successfully fixed
dzrmo@bergamont ~/src/f3-6.0 $ 

dzrmo@bergamont ~/src/f3-6.0 $ sudo ./f3probe --destructive --time-ops /dev/sdf
F3 probe 6.0
Copyright (C) 2010 Digirati Internet LTDA.
This is free software; see the source for copying conditions.

WARNING: Probing normally takes from a few seconds to 15 minutes, but
         it can take longer. Please be patient.

Bad news: The device `/dev/sdf' is a counterfeit of type limbo

You can &amp;quot;fix&amp;quot; this device using the following command:
f3fix --last-sec=15466495 /dev/sdf

Device geometry:
	         *Usable* size: 7.38 GB (15466496 blocks)
	        Announced size: 30.00 GB (62914560 blocks)
	                Module: 32.00 GB (2^35 Bytes)
	Approximate cache size: 7.00 MB (14336 blocks), need-reset=no
	   Physical block size: 512.00 Byte (2^9 Bytes)

Probe time: 2'30&amp;quot;
 Operation: total time / count = avg time
      Read: 1.40s / 32937 = 42us
     Write: 2'28&amp;quot; / 215152 = 690us
     Reset: 494.2ms / 2 = 247.1ms
dzrmo@bergamont ~/src/f3-6.0 $ 

[[[ Ran gparted and reformatted the drive ]]

dzrmo@bergamont ~/src/f3-6.0 $ sudo ./f3probe --destructive --time-ops /dev/sdf
F3 probe 6.0
Copyright (C) 2010 Digirati Internet LTDA.
This is free software; see the source for copying conditions.

WARNING: Probing normally takes from a few seconds to 15 minutes, but
         it can take longer. Please be patient.

Bad news: The device `/dev/sdf' is a counterfeit of type limbo

You can &amp;quot;fix&amp;quot; this device using the following command:
f3fix --last-sec=15466495 /dev/sdf

Device geometry:
	         *Usable* size: 7.38 GB (15466496 blocks)
	        Announced size: 30.00 GB (62914560 blocks)
	                Module: 32.00 GB (2^35 Bytes)
	Approximate cache size: 7.00 MB (14336 blocks), need-reset=no
	   Physical block size: 512.00 Byte (2^9 Bytes)

Probe time: 2'25&amp;quot;
 Operation: total time / count = avg time
      Read: 1.42s / 32944 = 43us
     Write: 2'22&amp;quot; / 215152 = 664us
     Reset: 493.5ms / 2 = 246.7ms
dzrmo@bergamont ~/src/f3-6.0 $

Dubious Micro-SD

UPDATE: I found Russian website where this same SD (sip14076k011a) was tested, although using different test software. Anyway, it also failed their tests – JUNK confirmed!

BTW, although the chip id is identical, the Russian website lists the SD (sip14076k011a)  as ADATA microSDHC Class-4 8-Gb. At least the size is basically correct in the ADATA branded card versus my unbranded version.


Posted in Electronics, hardware, Linux, software | Tagged | 2 Comments

Progress Report – Hall Transistor based Level Measure

Below you will find a progress report video. The video shows a demonstration of my work-in-progress project that I have mentioned, at least the 3D Print portion, in previous posts. The actual product is a powder level alerting system used in reloading. While reloading, if a case’s powder level is out of Tolerance, a beeper will sound. The firmware is written in C and C++ and while I am testing on an Arduino Nano the final product will be on a surface mounted ATTiny85. In fact all but two components on the circuit board will be surface mounted.

The only output on the device is a beeper and the only input is a single push-button. Despite this limitation I can change nine different settings based on the duration of the button press. The main body of the code uses a state machine with non-blocking code with the exception of routines that decode button presses and sound button press related beeps, which do use blocking subroutines.

I now consider the firmware to be complete. Next, I must start on the printed circuit board design and then fabrication. Once the product is finalized I will post an update. The entire product, both hardware and software, will be released open source when it is final. That is probably some months away.

By the way, I almost threw in the towel on this project because I could not get the hall effect transistor to be stable. After much frustration and, ultimately, a great deal of investigation, I discovered that the problem was that, during debugging, I was powering the Arduino device using a USB cable while also sending out debug serial ASCII text messages over the same cable. Apparently using serial data over the same USB cable that provides power was introducing sufficient noise to destabilize the hall effect transistor. Once my project switched over to a standalone power supply instead of using the USB cable, the hall effect transistor became stable. The final product will run off of a 1/2-AA battery. This bug should be of interest to anyone doing embedded system design – be careful about supplying serial data over the same cable that provides power.


Posted in Arduino, Electronics, hardware | Leave a comment

Revisiting+ WLX-652 e/w SnakeOS

NOTE: This was originally a May, 2015 post but I just revised it today, June 26, 2016.

Back in 2012 I wrote about the SnakeOS flashed WLX-652 device ( See Original Post ). As I said then, I actually purchased it back in 2010. It’s hard to believe it but that thing has been sitting on a shelf for five years.

WLX-652 Overview

WLX-652 Overview

Well, if you have read back in my blog you’ll be aware that I have in interest in IP-Cameras. I have a couple of cameras on my property that are aimed at my mountain view. I intend to add another on my chimney so that I can look for roof damage when I am away from home. This is because, during last February I was in another state for a month and during that time 77-mph winds ripped off part of my roof and then dumped snow on top of it. That is another  story for a another time and a different forum.

I share the URLs for my cameras with friends and give them the guest passwords. However, for some time I have wanted a way for them to be able to see several cameras at once, in a secure way yet without passwords. I felt that I needed a local server where the login/password process is hidden from prying eyes yet all the cameras could be simultaneously viewed in a web gallery.

It occurred to me that the venerable little WLX-652 might be sufficient for the job as my local webserver for my camera web gallery. It is! I described what I did below, but first, here is a screen capture of the web gallery that the WLX-652 serves up.

Capture of Gallery

Capture of Gallery hosted by WLX-652

SnakeOS is based on BusyBox and contains BusyBox HTTP Daemon (httpd) so it can host web pages. I knew that my web page needed to have any complexity on the client side so PHP was out. I searched for simple photo gallery software that only used HTML and JavaScript. I found what I was looking for at Dan Doicaru’s HTML-TUTS website (more later).

With SnakeOS you define the WWW folder in the admin section “Services->Webserver”:

webbase The folder /usb/snake1/www contains the gallery HTML code “index.html” and the folder “cgi-bin”.

Before I could work on the HTML, I needed to develop a CGI that would fetch snapshots from each IP-Camera and store them on the USB stick plugged into the WLX-652. I decided to write my CGI in shell script, which, on the WLX-652, is the fairly fully featured “dash” a derivative from Linux’s Debian distribution. A copy of the cgi script is at the bottom of the post, below the word ‘UPDATE’.

Here is what the current HTML “index.html” looks like:

&lt;!DOCTYPE html&gt;
&lt;link rel='shortcut icon' href='favicon.ico' type='image/x-icon'/ &gt;
&lt;title&gt;Connestee Falls North Carolina Cameras&lt;/title&gt;

&lt;style type=&quot;text/css&quot;&gt;
body {
	background: #222;
	color: #eee;
	margin-top: 20px;
	font-family: Arial, &quot;Helvetica Neue&quot;, Helvetica, sans-serif;
a {
	color: #FFF;
a:hover {
	color: yellow;
	text-decoration: underline;
.thumbnails img {
	height: 80px;
	border: 4px solid #555;
	padding: 1px;
	margin: 0 10px 10px 0;

.thumbnails img:hover {
	border: 4px solid #00ccff;

.preview img {
	border: 4px solid #444;
	padding: 1px;
	width: 800px;


&lt;script type=&quot;text/javascript&quot; src=&quot;cgi-bin/fetchimg.cgi&quot;&gt;&lt;/script&gt;
&lt;script type=&quot;text/javascript&quot;&gt;&lt;/script&gt;

&lt;div class=&quot;gallery&quot; align=&quot;center&quot;&gt;
	&lt;h2&gt;Camera Snapshot Gallery&lt;/h2&gt;
	&lt;br /&gt;

	&lt;div class=&quot;thumbnails&quot;&gt;
		&lt;img onmouseover=&quot;preview.src=img1.src&quot; name=&quot;img1&quot; id=&quot;img1&quot; title=&quot;Camera Undefined&quot; src=&quot;; alt=&quot;&quot;/&gt;
		&lt;img onmouseover=&quot;preview.src=img2.src&quot; name=&quot;img2&quot; id=&quot;img2&quot; title=&quot;Connestee West ONVIF&quot; src=&quot;&quot; alt=&quot;&quot;/&gt;
		&lt;img onmouseover=&quot;preview.src=img3.src&quot; name=&quot;img3&quot; id=&quot;img3&quot; title=&quot;Golfcourse View&quot; src=&quot;&quot; alt=&quot;&quot;/&gt;
		&lt;img onmouseover=&quot;preview.src=img4.src&quot; name=&quot;img4&quot; id=&quot;img4&quot; title=&quot;Connestee West Neighbor&quot;src=&quot;&quot; alt=&quot;&quot;/&gt;
		&lt;img onmouseover=&quot;preview.src=img5.src&quot; name=&quot;img5&quot; id=&quot;img5&quot; title=&quot;Camera Undefined&quot; src=&quot;; alt=&quot;&quot;/&gt;

	&lt;div class=&quot;preview&quot; align=&quot;center&quot;&gt;
		&lt;img name=&quot;preview&quot; id=&quot;preview&quot; src=&quot;&quot; alt=&quot;&quot;/&gt;


var img2elem=document.getElementById(&quot;img2&quot;);
img2elem.src= &quot;images/&quot; + img2;
var img3elem=document.getElementById(&quot;img3&quot;);
img3elem.src= &quot;images/&quot; + img3;
var img4elem=document.getElementById(&quot;img4&quot;);
img4elem.src= &quot;images/&quot; + img4;
var previewelem=document.getElementById(&quot;preview&quot;);
previewelem.src= &quot;images/&quot; + img3;

To maintain the website, I keep a folder on my desktop that is a duplicate of what is on the WLX-652’s WWW folder. Mostly edit the files on my desktop and use SSH to scp files back and forth. However, SnakeOS includes vi so, using ssh it is easy to edit files right on the WLX-652’s usb drive.

By the way, SnakeOS contains a functional cron and, briefly, I considered using it to periodically download the IP-Camera images.

My admiration for the WLX-652 has grown significantly. Who would have thought – a complete local webserver fetching and hosting images of multiple IP-Cameras for the current  total cost (including postage) of $33USD! The Raspberry-Pi would be what most folks would turn to for this task but it would cost significantly more (after case and PS added) and, quite frankly, is overkill for hosting a website like this.

UPDATE: A ‘like’ from reader of this blog, kittenswithselfies, caused me to read through this post once again and realize that it needed an update.

Occasionally, the WLX-652 would have its USB file system get trashed and I would have to rebuild it. I eventually tracked down the problem when I realized it only happened when after the WLX-652 had been powered down. Apparently, it was occasionally being powered down while a write was still in queue. Adding a ‘sync‘ command to the cgi script cured that problem. Next, I realized that I did not post my current, changed, the cgi script in this post. Consequentially, it is now posted below (with login/password and URL changes, for privacy):


# Written for WLX-652 Snake-OS
# Version 2.2
# NOTE: Verify that the following path is correct!
# Changing the usb stick can change this


rm ${photodir}*.jpg
sec=`date +%s`

echo "Content-type: text/javascript"
echo "var sec = '${sec}'"

# Fetch FI8904W Outside porch Camera still image
wget -q -O ${photodir}${cname}${sec}.jpg http://${camera}:${port}/snapshot.cgi?user=${username}\&amp;pwd=${password}
echo var img1 = "'${cname}${sec}.jpg';"

# Fetch C6F0SeZ3N0P0L0 h.264 Outside IPCAM (lil Abner)
wget -q -O ${photodir}${cname}${sec}.jpg http://${camera}:${port}/tmpfs/snap.jpg?usr=${username}\&amp;pwd=${password}
echo var img2 = "'${cname}${sec}.jpg';"

# Fetch Community's Axis Outside camera
wget -q -O ${photodir}${cname}${sec}.jpg http://${camera}:${port}/axis-cgi/jpg/image.cgi?resolution=800x600&amp;camera=1
echo var img3 = "'${cname}${sec}.jpg';"

# Fetch Neighbor's FI8918W Indoor Camera
wget -q -O ${photodir}${cname}${sec}.jpg http://${camera}:${port}/snapshot.cgi?user=${username}\&amp;pwd=${password}\&amp;count=0
echo var img4 = "'${cname}${sec}.jpg';"

Posted in ARM, Electronics, hardware, IP-Camera, Linux, Programming, software | 3 Comments

SMS from Arduino

A few weeks ago I was chatting with my mail carrier who is also a beekeeper. I mean LOTS of bees with some hives in remote locations. He has a friend that is working on a system that weighs hives and sends data over WiFi to a beekeeper’s desktop computer or server. The most important data is the hives weight although temperature and humidity are also useful. This system is good when the hives are close to structures with usable WiFi but useless in more remote sites where there is no accessible WiFi. I suggested that his friend investigate using cellular telephone SMS text messages instead where many more hives could have their data monitored.

I mentioned that I have just been reading about a small printed circuit board that could be used with an Arduino that would be perfect for remote beehive monitoring. It is an evaluation board called “SIM800L EVB”. They are available on eBay in the $6-to-$10US range. I purchased mine from Philippines seller “holi_day_sales“. I was careful to purchase a version that has on-board voltage regulation for that I could use five volts. Some versions have USA frequencies and others are for Europe of Asia. Caveat Emptor – they are NOT all alike! They were also available from Seeed Studio but they currently seem to be out of stock. In any case, Seeed’s wiki is useful. A remote solution is possible if the hive has at least one bar of AT&T cellular telephone coverage allowing communication by SMS (TEXT). Such a solution would have a reduced parts count to a single microcontroller, such as an Atmel ATtiny84 (Prototypes could use an Arduino board), sensors for weight, temperature and humidity, A solar panel with battery and charger would provide power.

I’m not sure if my mail carrier’s friend will pursue using SMS text messages for his hive monitoring system but, nonetheless, I became interested in testing the little “SIM800L EVB” board, which is exactly what I did this afternoon. I’ve only done a little testing but the SIM800L performed with flying colors. It is very easy to work with. I cheated a bit and relyed on Ayoma Wijethunga’s excellent blog article titled “QUICKSTART SIM800 (SIM800L) WITH ARDUINO“. You need little else to get started with the “SIM800L EVB”.

For my tests I used a H2O Wireless GSM SIM card. Specifically, it uses the AT&T GSM cellular network but is marketed by H2O Wireless at $10 for 90-days of service at 5 cents per text message sent or received. That allows two text messages to be sent per day. They also sell more expensive plans should more data be needed. I surmised that, by omitting extraneous characters, a single text message could easily hold a hives weight, temperature and humidity. For example, a hive weight of 125 pounds at 72 degrees Fahrenheit and 30% humidity can be represented by the nine character string “125072030” using three digit positional data of three characters each representing “Weight in pounds”,“temp in Fahrenheit”,”Humidity in percent”. Given that a single SMS message can contain 160 characters, a single message has another 151 characters available for other data, should it prove necessary. One possibility would be to have one message represent the data of 17 bluetooth networked co-located hives that share a single SIM800L board.

So, below are images of one of my tests. I am sending a simple “Hello World” type message from the SIM800L board to my Android smartphone. I sent “Hello,World from Seed” because I used the Seeed library, but the SIM800L module is NOT a Seeed module.

sim800L / Arduino Setup

sim800L / Arduino Setup

By the way, the test setup shown above has some extra components and wiring present because they are for something else that I am working on and I wanted to leave them in place for that project. Also, the little rubber-duck antenna is propped in a vertical position by the blue Ethernet cable that also has nothing to do with this project.

sim800 Arduino Program Output

sim800 Arduino Program Output

SMS Received by my phone

SMS Received by my phone

I should point out that there are commercial products that do something somewhat similar, although at a price that may exceed all but large commercial businesses. For example, see:

Posted in Arduino, cellular, Electronics, hardware, Programming, SMS, wireless | Leave a comment