Search This Blog

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.

Friday, September 14, 2018

Portable F103 - Power source detection

Projects / F103 Pod

I did some power measurements.  They agree with the published values on the datasheet.  The LED backlight can add another 2 - 5mA depending on brightness setting.


To converse battery life, the firmware can optionally drops the clock speed to 12MHz. This should allows for a battery life of 10+ hours with the larger LiPo and 5+ hours for the smaller one (vs 2+ and 1+ hours at full speed.)  The actual current consumption may vary depending on the amount of time the CPU is active vs sleep.

The firmware has to be able to detect if a charger or USB is present.  If so, it can run at the full clock speed of 72MHz

The STM32F103 is quite old and does not have a charger detection hardware built-in.  The USB data pin on the STM32F103 can be used as GPIO and is able to detect USB connection. and some of the more common chargers.

Silicon Labs EFM8UB1 on the other hand can detect the complex charging protocol in USB spec. Apple chargers can also be detected as it USB pins can also function as ADC inputs.

Charger Detection

For the STM32F103 FT (5V tolerant) at VDD = 3.3V, the VIH threshold is
0.42*(3.3V - 2V) + 1V = 1.546V (min)
STM32F103 I/O Static characteristics
A simple USB chargers that have data pins D+ and D- shorted together can be detected by configuring the   D- line as a GPIO input pin with an internal pull-down resistor.  The 1.5K pull up from D+ is looped back by the connection to the D-.
The voltage at the D- is 3.3V * 50K/(50K+1.5K) = 3.2V which is a logic '1'.
Apple chargers uses a resistor network to encode the current capacity.  For the 1A chargers, they use a 43K/ 51K voltage divider on the D- pin.

Apple 1A charger resistor networks
The parallel resistance of 51K//50K is around 25K. The voltage at the D- is
5V * 25K/(25K+43K) = 1.84V which is a logic '1'.   This is also treated as a charger.
For Apple 0.5A charger,  the voltage is at 1.25V which is within undefined area and cannot be read reliably.


USB detection

There are 15K pull down resistors on the USB port.  The firmware detect that by configuring the input pin with an internal pull-up resistor.
The voltage at the D- is 3.3V * 15K/(50K+15K) = 0.76V which is a logic '0'.
If the pin is a '1', then it could mean that the input is floating or that it is connected to an Apple 0.5A or 2.1A charger.  I came up with a way to detect whether a pin is floating a while back, but I won't bother here.

The detection code is listed below. I added in Delay(0x80000) for the connector contact debouncing.  The smaller Delay(0x200) is there to give a bit for parasitic capacitor to charge up and stabilize.



Status is set to Pwr_Unknown as further detection is needed by secondary mean.  If the Battery voltage is above 4.3V that means that the Power Switch is in the On position and external power source is present.

Note: Blogger messes up my code each time I go into the editor.  It is too much work to fix their problem.  I am giving and switching to using screen captures.