Search This Blog

Saturday, August 31, 2019

USB meter modding - Part 1

USB meters can come in handy for measuring the voltage and current. While they may have 3 digits display, some of them do not actually have the resolution nor are calibrated.

This is a mod for a $2 USB meter to to improve on the resolution and accuracy closer to my digital multimeter with the added bonus of much lower voltage drops. My modifications and calibration (part 2) makes up for the loose tolerance parts.

Modded meter reads 13mA (3mA for the LCD meter + 10mA for serial dongle)
The LCD meter cannot see the dongle even though the current is within range.
I have decided to modify one for an impulsive weekend project. It is a KW203 from a few years ago for about $2. The ones I saw are overpriced ($10-$20) and you can get really fancy LCD ones for about $3.

It uses a SO18 wide package, so a replacement microcontroller can be fitted within the footprint.  It is simple enough that the I/O mappings can be traced.

PCB with microcontroller removed.
The current measurement is done with a 0.01R sampling resistor placed in the ground connection between the input and the USB connectors. A SOT23-5 opamp in a non-inverting configuration provides 48X gain.
The amount of voltage drops is lower than the average multimeter.

The voltage measurement is done with a voltage divider of 15K in series and 2K to ground.  There is a ceramic capacitor in parallel to provide the low impedance for the ADC.

There is a group of 5 resistor footprints behind the "Charger" USB connector.  They are to provide the "Charger" voltage divider for Android/iOS charger.

There are foot prints for a couple of SOT23 sized trimpots for both measurement, but they are bypassed with a couple of 0 ohms resistors jumpers instead.

There is a MD78U30 3V LDO to provide a 3V rail for the microcontroller as the meter is supposed to be able to handle 3.2V - 10V.  There is a small 10uF tantalum bulk decoupling cap on the output rail. There are no additional decoupling caps provided.

Cheat sheet I used for wiring up the microcontroller
The two IC are the old and the replacement microcontroller.  I have decided to use the STM8S008F3 as it has just the right number of I/O needed: 14 I/O for driving the 6 digits multiplexed 7-segment LED display and 2 ADC inputs for the measurements. If I scale the input correctly, the 10-bit ADC, I should be able to get close to 3-digit resolution.  I am using oversampling to improve on the resolution, but the actual resolution depends a lot on the noise floor and type.

There are a few gotchas:
  • PB4, PB5 are "True" Open drain pins, so they can only be used for the common cathode and not the segments. PA1, PA2 are standard GPIO vs the rest of the HS (High Sink), so those segments might be slightly dimmer. 
  • There are no series resistors, so the LED is current limited by the GPIO driver resistance.  The power rail is set at 3V which helps a bit. The LED switching can affect the ADC reading as the ADC has no internal reference and use the power rail as reference.
  • There are 3 ceramic caps for this part. VCAP is the 1.8V decoupling cap for the internal regulator, and one for the 3V rail. The NRST can probably be ignored, but I connected it per datasheet  recommendation.
  • There are no spare I/O. The SWIM pin is also used in driving the first digit and its GPIO function is disabled when the debugger is connected.
  • The 7 segment display only have decimal point at the first digit.
  • The grounding isn't good and 4-wire connection isn't used at the sampling resistor which can affect the linearity at higher currents.
The part is small enough to fit within the footprint. This is a quick and dirty hack, so I am not going to make a custom flex PCB at OSH Park and wait for it.

Replacement microcontroller soldered
I soldered in the microcontroller with some fine magnetic wires and even wired in the required capacitors on top of the chip.  The extra wires are the SWIM, NRST pins for the hardware debugger/programmer.

Test display
After a bit of debugging, I got the timer IRQ to turns on the column driver and dumps out the corresponding digit stored in the buffer at a refresh rate of ~59Hz.

So far the I/O seems to be going to the right places and the hardware debugger works. The current drawn is about 10.5mA.

Project file: https://github.com/FPGA-Computer/USB-Voltage-Current-Meter

  • I found a KW203 reverse engineering article here after my mod.
  • There are also panel meter with a STM8.
  • I have seen one of the more LCD fancy one last week and it seems to be using a 20-pin TSSOP microcontroller. 




This one might have a STM8S003 and a 4 pin programming connector.

Thursday, August 15, 2019

XVCD rev2 - part 1

I tried implementing a JTAG programmer for Xilinx devices using the ESP8266, but I wasn't happy with the overall design - Arduino, bitbang JTAG, 2.4GHz WiFi etc.

There is a problem with the XVC protocol is written.


Normally the TMS vector needed is a lot shorter to get a device into programming mode while the bulk of the programming data is handled in the TDI/TDO.  The protocol expect that both the TMS and TDI vectors are output to the device while receiving the TDI in one go. While this provides the maximum flexibility, it is the part that causes a bottleneck on the performance.

I though using the SPI would have improved the situation, but I guess I didn't read the fine prints carefully to realize that I need to have both outputs.

I am in the process of working on my new design using a popular cheap but capable STM32F103.  It is the same size as the ESP8266 module and consumes a lot less power.
3D model
Top side
Solder side
I am using both SPI in the STM32F103 part for the JTAG interface.  SPI1 acts as the master SPI (for TCK, TDI, TDO) while SPI2 (for TMS) is the slave.   Both the SCK are wired together to synchronizes the two SPI.
SPI1 and SPI2 are used to drive the JTAG signals
 .
ST wired the SPI2 to the AHB1 clock domain (36MHz) which limits the overall data rate to 18Mbps instead of the 36Mbps supported by SPI1. The bottleneck in this design is Full Speed USB (12Mbps).

My bare metal (i.e. no libraries) SPI DMA + interrupt code works on first try! It is probably a lot easier (for me) than baby sitting the 3 SPI data stream and keeping them well fed with firmware loop.  It also frees up the CPU for the rest of the code.


The SPI is set up for 8-bit transfers using 3 DMA channels for each of the vectors. A bitbang routine handles any left over bits.  It is hooked to the DMA completion IRQ and takes 3us for the switch over. The bitbanging is at  1.8Mbps which is 1/10 speed of SPI, but it only need to deal with at most 7 bits of data.


The next hard part is dealing with Windows, USB and the networking stuff.

Friday, December 21, 2018

STM8 Timer - Irrigation

Projects / Misc 8-bit uC projects

Water level sensor

The TPP223 (.pdf) touch sensor I bought finally arrived.  As usual, the LED is just too bright.  I change the series resistor (bottom in black) to a 2K (0603).  A small value capacitor (0-50pF) can be added to the empty footprint at the top right corner to reduce the sensitivity of the sensor.

The default output is push-pull, active high, non-toggled.
There are two solder bridge jumpers: A, B to set the following options.
A: (AHLB) pin 4 - Active low
B: (TOG) pin 6 - Toggle


For testing, I used a small piece of double side tape to stick it to the side of a plastic container and slowly filling it with water.  The LED lights up for a minute or so.


I think this could be useful for determining if water level reaches the high water mark.

I cut up a plastic bottle into two halves and fitted the top end with a short PVC jacket from a stranded CAT5 patch cord.  I used lots of hot glue to seal the joint. The top end works like a funnel. I drill a hole on the bottom half for the exit.


I tried to make a gentle L bend without crushing the PVC jacket.


I am trying to avoid using regular tapes as they tends to dry up and crack under sun light. I cut up 3 strip of paper about 2" wide x 11" long.  I applied a generous amount of white glue and use it to wrap it around the plastic bottle to hold it together.  This forms a paper mache shell to hold the two halves together.


I soldered in a 22pF capacitor to the empty pads on the touch sensor board.  This lowers the sensitivity a bit. I soldered a short piece of wire (~1cm) to the corner pad of the touch sensor to a small copper foil.  The bottom part of the copper foil is used to set the high water mark.


The output of the board drives a 2N7002 MOSFET which converts it to an Open Drain output.  This will be wired in parallel to the light sensor.  The on resistance of the MOSFET is about 10 ohms.

I have to make my trip much sooner. I have given away two of the plants as I can always grow more.  Only been running it for a few days on the remaining one and it seems to be okay.

Things I have learnt so far:
  • The pump I used is a centrifugal pump which requires that the pump to filled with water.
  • The pump produces a lot of electrical noise generated by the DC motor during commutation to reset the microcontroller.  I have included ceramic cap near the output connector on my PCB, but that wasn't good enough.  I had to add a 0.047uF cap at the pump side end of the long cable. I added another one to the other end of the cable for good measure.
  • The water drains out of the container very quickly making it hard to measured..  There are ways to stop the drainage.  Right now I set the timer for a fixed time instead of relying on water level detection
  • There was water leaking out of the seams in the pump, so I touched it up with super glue. That fixed the issue.
  • Water from the container relies on gravity.  Some water droplet ends up sticking to the small diameter silicon tubing.  It amounts to less than a couple of cc.  Try to keep he slope of the tubing uniform to minimize the water retained. I might try using a slightly larger diameter tubing. It probably not going matter too much as they'll get pushed out next time.


Friday, October 19, 2018

STM8 Timer

Projects / Misc 8-bit uC projects 
This is one of those weekend project.  It is a timer built using STM8 microcontroller for controlling LED light strip and a water pump. It can be used for other things.

There are two switched outputs: 12V 2A for LED strip switched by a MOSFET and a MC34063 switch mode power supply is used to generate the 2.5V for a small pump.  The output voltage can be altered by changing the feedback divider.  The buck converter can be disabled by sending a logic '1' via diode D3 to its feedback pin. There is a leakage path  (~0.4mA) to the output from GPIO via D3 and R7.  The whole block (except C2 and C4) can be removed when not needed.

I am using a 5.1V Zener diode as a shunt regulator for the 5V rail while I was waiting for my 78L05 order.  I notice that there are some artifacts on the LCD with the 78L05. I'll guess I can stick with the Zener diode or  add a bulk electrolytic or tantalum 10uF capacitor across the 5V rail.

There is a sensor input and two unused solder pads for I2C.



The LCD is connected to the main PCB with two sets of 6 conductors ribbon cables.  I am using 4-bit mode on the LCD. I have wired the R/W pin for polling the busy flag in the LCD controller.


There is a 3-pin connector for the SWIM hardware debugger.

LCD delay vs polling

The datasheet for the character LCD lists the timing for each of the instructions.  These are the worse case timing that include timing variations due to component variations, voltage and temperatures. Most of the projects implements a delay loop to meet these timings.


The LCD timing can be tighten up by polling the internal Busy Flag to determine when the LCD is ready for the next command.  This requires an additional GPIO to control the R/W signal.


The instruction time can be less than the values in the datasheet which have some margins for component variations.

TIM1 is used as a trigger for ADC and timer interrupt every 5ms for a software RTC implementation.
I used a prescaler of 1 and a reload value of 60000 in TIM1_RELOAD.
12MHz/60000 = 200Hz
With calibration, the reload value can be used to trim the accuracy to be within +/- 0.72 sec per day. 
(24 Hr/day * 3600 sec/Hr )/60000 = 1.44 sec/day
I have implemented a menu for trimming.


The timer reload value could be changed in the IRQ service routine from a  software phase accumulator to further increase the resolution to fractional values. The difficult part is to automate the calibration against an external time reference (e.g. GPS).

The ADC alternates between the buttons and sensor inputs.  They are managed inside the ADC IRQ and their results stored in global variables.  The key input routines are run inside the IRQ.

The ADC value is matched to a look up table for decoding the buttons.

const uint16_t Key_Value[]=
{
  510+ButtonTolerance, 194, 340, 140, 510, 163, 255, 123
};
  • count is used to keep track of the amount of time that the button(s) are pressed.
  • code is used to store the code for button. KEY_FLAG bit signalnifies a key make event
  • A button is recognized if it reaches KEY_THRESHOLD (passed debouncing)
  • If the count reaches KEY_CNT_MAX, then a key make event occurred with a  KEY_LONG attribute.  The counter is then loaded with the KEY_RELOAD value.  The difference of these values controls the key repeat rate.
typedef struct
{
  volatile uint8_t code;
  volatile uint8_t count;
} key_t;

enum keys { KEY_MENU=0x04, KEY_DEC=0x02, KEY_INC=0x01, KEY_MASK=0x07, 
            KEY_LONG=0x20, KEY_REPORTED=0x40, KEY_FLAG=0x80 };

#define KEY_REPEAT_RATE  4
#define KEY_THRESHOLD  5
#define KEY_RELOAD  50
#define KEY_CNT_MAX  (KEY_RELOAD+TICKS_PER_SEC/2/KEY_REPEAT_RATE)

These data structures are used to control a simple user interface using 3 buttons.
  • Value is a pointer to the item which can be an 8/16-bit integer or the text label for a UI_Menu_t structure or a function.
  • Modified is a pointer to a flag variable that get set when an item is modified.  It is also used as the pointer to a function.
typedef struct
{ 
  void    *Value;
  uint8_t  *Modified;
  uint8_t  X;
  uint8_t  Y;
  uint8_t  Width;
  uint16_t Min;
  uint16_t Max;
  uint8_t  Flags;
} UI_Item_t;

typedef struct
{ 
  uint8_t   *Text;
  UI_Item_t *Items;
  uint8_t   Size;
} UI_Menu_t;

enum DataFlags { D_12H, D_U8, D_U8Z, D_U16, D_Menu, D_Function };



This is inside the "Alarm" sub-menu. (See further down for an updated version)
A long press of the Edit/Exit key is used to enter/exit the setting menu.  The settings are stored in the STM8's internal EEPROM.

I have selected the items can be selected by using the buttons.  An up/down arrow appears on the right hand side of the item.  The Prev/Next key can be used to decrease/increase the value by one.  When the key is held down, the values auto decrease/increase by 10.  The Edit/exit key is used to exit the editing.


The firmware so far consumes a fraction of the available memory - about 2.8kB. (8kB FLASH, 1kB RAM).

I made a make shift light sensor by filing the top off a 2N2222 (.pdf) TO-18 metal can package to expose the die inside.


I use a bit of hot glue to seal the package.  It is a bit of dust and dirt magnet.  I hope it doesn't turn yellow like epoxy after exposing to sunlight.  I covered the sensor with a bit of plastic from an antistatic bag to reduce the sensitivity.

I paired it up with a 2N3904 to to improve on the gain as the 2N2222 die is not sensitive to light. They are wired as a Darlington pair.



I guess this has to do until I get my CdS photoresistors in the mail.  It will be connected directly across the sense input.


The following is the Alarm menu.  The alarm time is set to 7:00am and the pump goes on for 3 minute.  The LED is set to supplement the ambient light.  It turns on whenever the ADC value is above 650 within a 12 hours period.  A bit of hysteresis is added in the code to minimize the lights toggling.


This replaces the plug in mechanical timer that runs warm (2W).  When running in idle, power consumption at 12V is around 14mA. The wallwart is cool to the touch and below the resolution of the cheap wattmeter I have.


I hooked it up to the LED strip for my urban window garden. The sensor is place above the LED strip and pointing outside the window.   The LED strip will be switched off to save power when the ambient light has cross the set threshold.  It was still dark outside.


The timer is hanging from the mounting holes on the LCD.  I am still waiting for the pump and drip irrigation parts to come in.

Part 2: https://hw-by-design.blogspot.com/2018/12/stm8-timer-irrigation.html
Files are in github: https://github.com/FPGA-Computer/Timer

Monday, September 24, 2018

Candle stove

Projects / Preparness

Two tornados showed up.  The second hit a major power distribution transformer and knocked out the power grid in my area for 48 hours. At one point there were 200,000 or so out of power.

Like most cooking shows, I made one previously. This is my emergency bootle with matches, candle, and a dry pack.


The lid is a candle stove.  I let it burnt a bit to melt the wax to soak the cardboard  and tried to shape the wax a bit so that it would fit the bottle.


The cross is made out of thin corrugated cardboard that had slots cut in them.


It light up very easily.  It turns out the cardboard and pieces of wax would just light up easily.


There is a lot of carbon soot in the flame and it is very messy.


That amount of wax is sufficient to make a pot of instant noodles.

or reheat a pot of homemade soup.


Advantage: Simple to build, high energy density, not having to deal with storing liquid fuel.
Disadvantage: very dirty flame, lots of carbon soot coating the cookware, low temperature.

Next time I'll see if I can improve the fame by having the wax vapor premixed air before combustion like my kerosene burner.

Links:

Backout:

Here is a picture of my city in the backout.  It kinds of looks like some rural area or North Korea.


As of this morning, they have restored the power for all but one city block by using the redundancy in the grid.  They are going to rebuild the substation in the next coming months.