Using Bondic Plastic Welder (Glue)

I was given a Bondic applicator a few months ago:

Found here for about $23:

I finally got around to using it today. The stuff works great for me.

I noticed one of the bars of the luggage rack of one of my old steel Jaguar models had been broken.

I applied a pin-point dot of glue to the upright support – the applicator is about as big as a .5mm lead pencil. I carefully aligned the bar onto the support and then used the enclosed UV light to cure it in 15 seconds.

It formed a good tight bond, with no mess.

luggage

Posted in c-Misc | Tagged | Leave a comment

Loose Part Storage During Electronic Device Repair

I just tore down my old Realistic DX-390 radio to look at fixing its sticky keypad. I had lots of little parts to keep track of while doing so. As I was working on this, it occurred that others may find my parts storage trick as useful as I do.

I picked this trick up some time ago. I have no idea the source of the original tip. I suspect it was from some book I read.

I keep a stack of 3oz paper cups at my work bench. When I start disassembling a particular device, I flip over a paper cup and put each part or series of like parts (e.g. external case screws) into a cup.

As I remove each little part it goes into its own cup and I stack that cup on the prior cup. When I’m done I have a nice stack of cups:

parts-fig-01

Now I not only have each part separated from the others, but I also have the removal sequence saved due to the stacking of the cups. Note the big plastic cup to the right. I keep big pieces in it.

When it is time to reassemble the parts, I simply remove each cup from the top of the stack and reinstall the parts in that cup.

I can still have trouble remembering where the parts go, so I sometimes stick a note in the cup to help id the parts:

parts-fig-02

I also tend to take pictures of the device during tear-down to help remember where all of the parts go. Smart phones are sure handy!

 

Posted in c-electronics | Tagged | 2 Comments

Switch Debouncing and Waiting for a Button Press

For the several years I’ve been working with arduinos I have went thru quite a few variations of switch debouncing. Some I’ve found on line, some I’ve written myself. Most of the ones I’ve found online I felt were kind of complicating for what I needed, but then when I write my own they tend to be too simplistic.

In the past 6 months I have settled on the following procedure. It is fairly simple and, as of yet, I haven’t had a problem with it.

I don’t really know where this procedure originated. I suspect it is partially from the Arduino cookbook with probably a tweak or two of my own.

//-----------------------------------------------------------------------------
// Get current keypad signal, debouncing. TRUE is returned when key is pressed
// which is reverse of the actual signal due to pullup resistors.

boolean keyDeb(
    int                    pin,
    const int             bounceDelay = 10
    ) {

int                        counter;
boolean                    prevState;
boolean                    state;

prevState = digitalRead(pin);

for (counter = 0; counter < bounceDelay; counter = counter + 1) {
    delay(1UL);
    state = digitalRead(pin);
    if (state != prevState) {
        counter = 0;
        prevState = state;
        }
    } // for

// NOTE: since pullup resistors are used, pin logic is reversed (pressing button returns false). keyDeb
// returns the reverse state of the pin, so logic is what you expect (e.g. pressing button = true);

return !state;

} // keyDeb

To determine is a switch is closed just test for true

if (keyDeb(pin) == true) { do whatever}

keyDeb waits 10ms for the switch to settle. For the switches I’ve used, this has always been acceptable. If you have a particularly noisy switch, you can specify a different bounce delay:

if (keyDeb(pin, 20) = true) { do whatever }

I use momentary contact switches often. When using them,  a simple test, like the above,  isn’t really enough. If I see the switch is pressed, I want to then wait until it is released to execute the code. Otherwise, I’m probably going to execute the code repeatedly until the user released the key. To solve that problem, I use code something like this:

if (keyDeb(pin) == true) {
    while (keyDeb(pin) == true) {}     // wait for the switch to be released
    << do whatever >>
    }

There are some programs where I do quite a bit of user interacting – waiting for them to press a switch to continue. For those instances I use a function I call keyWait:

void keyWait(
    int                    pin
    ) {

while (keyDeb(pin) == false) {}
while (keyDeb(pin) == true) {}

} // keyWait

When I need to wait for them to press the momentary switch connected to pin <p>, I just code:

keyWait(p);

Just remember, all the code comes to a stop when keyWait is called. If you need to be doing something else while waiting for the user, this is not the procedure for you.

 

 

Posted in c-arduino | Tagged | Leave a comment

Wiring Wiz820io Ethernet Module to Teensy 3.1 (or 3.2)

I have a Teensy 3.1 and Wiz820io Ethernet Module I want to connect together. PJRC does sell a little shield for the Wiz820io, but I plan to mount the Teensy to a PCB and want to do the same with the Wiz820io rather than use this shield.

I immediately had issues which I incorrectly blamed on drivers. Had this been any MCU other than the Teensy, drivers would have been a good guess. I was puzzled as to why I would have driver issues given PJRC was selling the shield. It should work, yet didn’t.

To make a very long (as in 8 hours) story short, the root of the problem lies in the Wiz820io’s RESET pin. I finally discovered that you MUST properly provide power to this pin to get the Wiz820io up and running. When you do, the two lights on the Wiz820io will come on.

But even after discovering the necessity of the RESET pin, I could not get the drivers to work. In my research I found one person telling another to toss their Arduino Due and use a Teensy because the Teensyduino had all the necessary drivers. OK, I *must* be using the proper drivers, and now I know the trick of the RESET pin, what else am I missing?

The final clue is in the PJRC shield wiring diagram:

Teensy3   SD Card   WIZ820io      MCP1825     JUMPER PADS
-------   -------   --------      -------     -----------
 4        2:CS
 8                                             Left Side
 9                  RESET
10:CS               SS
11:DOUT   3:DI      MOSI
12:DIN    7:DO      MISO
13:SCK    5:CLK     SCLK
VIN                               1:IN
          4:VDD     VIN33,VIN33   3:OUT
GND       6:VSS     GND,GND,GND   2:GND+TAB   Right Side
                    PWDN                      Center

The Wiz820io RESET pin is connected to Teeny’s pin 9. I’ve been using 2, well, just because it was convenient. Switched it to pin 9 and BAM! It worked. DHCP assigned an IP address and I could ping it.

The Teensy ethernet library does work properly for the Wiz820io, you just need to make sure you tie the RESET pin to Teensy’s pin 9.

With that done, here is how I wired a standalone Wiz820io module to a Teensy 3.1:

teensy-wiz820io-fig01and here is the actual device:

teensy-wiz820io-fig02

Some additional notes:

Most of my testing was done using Arduino IDE 1.6.5 and Teensyduino  1.25 because I figured the latest drivers would be there.

Once I had solved the issue as being the RESET pin, I then went back to Arduino IDE 1.0.6 and Teensyduino 1.24 which is what my ‘stable’ development platform is at the moment (I really don’t like developing on a release-candidate. I have enough issues, thank you very much!)

 

Posted in c-teensy | 5 Comments

Resetting / Rebooting ATTiny85 with Watchdog Timer (WDT)

I was expecting this to be a no-brainer. I use WDT on Arduinos w/o any trouble. The code for Arduino would roughly be:

#include <arv/wdt.h>

...
wdt_enable(WDTO_1s);
while (true) {}

After one second, the arduino reboots because of the WDT.

That does not work for the ATTiny85. It wants to call the WDT_vect ISR instead and somehow (at least for me) hangs up such that I have to remove power from the ATTiny85 to get it running again.

After hours of banging my head against the wall and searching every source repeatedly I finally was able to put together the following code which correctly reboots the ATTiny85:

#include <avr/wdt.h>

void reboot(
    ) {

cli();
WDTCR = 0xD8 | WDTO_1S;
sei();

wdt_reset();
while (true) {}

} //reboot

void setup (
    ) {

    wdt_disable();

    }

In this example, the WDIE bit is set to 1 which is necessary to get the MCU to reset. Evidently wdt_enable() is not doing that for the ATTiny85. The other possibility is that the wdt_enable() procedure is not fast enough as the ATTiny85 requires everything be set properly in 4 clock cycles.

Note: You MUST include wdt_disable() as the first instruction in setup(). I tried going without this and it hangs under that condition as well.

Either way, this code is working for me, so after 2 evenings of frustration, I can proceed with my project!

Posted in c-tinys | Tagged | 7 Comments

How to Crimp Your Own Dupont Connectors to Jumper Wires

I really like to use pre-terminated M/M, F/M, and F/F wires such as these found on amazon:

The 0.1″ pins fit into breadboards and most breakout board male or female headers.

Sometimes, though, the pre-terminated jumper wires are either too long or too short and I want to make a custom jumper wire.

To do this, you will need a crimper, male and female terminals, housings, and 22AWG wire.

I purchased an IWISS SN-28B Crimper from Amazon:

I purchased male and female pins from pololu:

https://www.pololu.com/product/1931

https://www.pololu.com/product/1930

crimping-fig1

and also the connector housing:

https://www.pololu.com/product/1900

I had no luck finding an explanation on how to crimp the terminals onto the terminal and destroyed a few learning. So I decided to post an instructional video of how I crimp the ends with success:

Update: I’ve had this for about a month now and have found multiple unexpected uses for it like building decent 9V breadboard connectors:

batt-pin

Oct 2016 Update:

Everyone complains about the clarity of the video, and they are right – it sucks. I use a lumix dmc-lx7 which is a great still camera. But the video can suck. It seems it focuses at the start of the video and never again so close up videos like this don’t work well.

Admittedly, I never really expected this video to be viewed by anyone but myself so I didn’t care. Surprisingly, it has ended up being my top video.

Rather than waste time trying to make another video that will almost certainly have the same issues, I will post a series of stills here which should make the process much clearer.

Here is an enlargement of a dupont terminal:

crimp-01a

The crimper will bend two sets of tabs (though there are actually 3 sets). The far right tabs will attach to the insulation while the center set of tabs will attach to the conductor. The very small set of tabs right before the bridge are not bent (at least not by this tool).

First, prep the wire by stripping it such that the insulation is going to be grabbed by the first set of tabs and the conductor by the second. The bridge gives you a little slack so you don’t have to be too exact on where to cut the insulation:

crimp-01b

Now note the ridge inside of the tool’s jaw. You are going to align the terminal such that the left side of the insulation tabs (using pic above) butt up against this ridge.

crimp-02

Here is the terminal in place in the tool with the tabs against the ridge (note that the .1″ style terminals use the center crimp on the jaw):

crimp-03

Now close the jaws just enough to hole the terminal in place:

crimp-04

Here is the other side:

crimp-05

With the wire already stripped and the tool holding the terminal snuggly, it is fairly easy to insert the wire into the terminal:

crimp-06

Do take another quick look to verify the conductor is past the 2nd set of tabs before you squeeze the tool tight and finish the crimp.

here is the completed wire and terminal:

crimp-07b

May 2022 Update:

The link to the video has been replaced with a new video that provides much sharper images.

Posted in c-electronics | Tagged | 3 Comments

Testing LinkSprite Caller ID Module (based on HT9032) with a PC

I would like to receive caller ID using a Raspberry Pi. I started off trying to use a winModem which failed epically. I then purchased a Trendnet TFM-56U1 which has also failed.

The TFM-56U1 modem works fine in all regards except for receiving caller id. The first one I had would only report caller id about 1 time in 10. I returned it and the second won’t report caller id at all.

After contacting Trendnet, their response is this modem will not support caller id (even though it obviously did at one time based on all the people using it specifically to obtain caller id).

The US Robotics model 5637 modem purportedly supports both Linux and caller ID, but at $40+, it is really too expensive for my testing since in the long run it won’t be my final solution anyway.

So I went looking for some device that would serially transmit caller ID. I found it in this LinkSprite Caller ID Module:

linksprite cid fig1

Which I purchased from here for $30.

http://store.linksprite.com/pstn-caller-id-module-for-arduino-pcduino/

Yes, it is not much less than the USR modem, but I’m thinking the HT9032 chip it is using may well be in my final design.

Resources

In getting this to work, I referred to the following resources:

Wiring

I used an FTDI breakout board like this to interface the CID unit to a PC’s USB port:

The FTDI board is wired to the CID as follows:

linksprite cid fig2

Now connect the USB cable to your PC. It should find the drivers w/o much trouble if you used any FTDI device in the past. If not, you will have to locate the drivers.

Once the drivers are installed, the CID boards is accessed as a serial port:

linksprite cid fig3

Now connect a terminal emulator of your choice to the COM port using 1200 baud:

linksprite cid fig4

Once you connect to the CID board, garbage is going to start printing. That is OK. Well, appears to be normal anyway. According to the data sheet, the output line is held high when there is no data. That seems to translate to garbage being transmitted.

Here is what I see between calls:

linksprite cid fig5

My terminal emulator displays control characters, so I can see *everything* being transmitted. For example NU = null or 0x00.

Once I receive a call I see:

linksprite cid fig6

Removing the ‘garbage’, I’m left with:

linksprite cid fig7

Here is a break down of the call data:

UUU...UUU

When call data is about to be presented, the CID board will transmit alternating 010101… for 300 bits. Those 01’s become a string of ‘U’s.

3/4

The CID board then transmits 180 1’s. For the serial port, this may end up as one or more random characters.

When the CID board outputs a 0x80, that is the beginning of the actual data.

ASCII      HEX     Dec   Len   Pkt Position   Desc
<80>       80      128    1    N/A            Start Packet
'          27       39    1    N/A            len of entire CID string (start with next byte, exclude checksum at end)
<sh>       01        1    1     0             indicates packet is date/time
<bs>       08        8    1     1             len of date/time packet
date/time                 8     2             05221609
<sx>       02        2    1    10             calling line packet (e.g. phone # of caller) 
<lf>       0A       10    1    11             length of phone# packet
phone#                   10    12             8005551212
<bl>       07        7    1    22             name packet
<si>       0F       15    1    23             length of name
name                     15    24             wireless caller
<          3c       60    1    39             checksum

After this packet data, the CID board will begin transmitting garbage again.

 

 

Posted in c-electronics | Tagged | 10 Comments

USB Dial Up Modem for Raspberry Pi

For the first time in probably 15 years, I find myself needing to use a modem. This time on a Raspberry PI.

I have a few old modems in the junk bin, but they need an RS232 serial interface which would be a pain to replicate on an RPI. So without much research I purchased a Hiro USB modem.

What I received was a USB “winModem”. It’s been so long since I have used modems I completely forgot about WinModems. To make these modems as cheap as possible, much of the signal processing was pushed off onto the host PC. These winModems require fairly sophisticated drivers.

Realizing this after I purchased a winModem, I tried unsuccessfully to find any kind of driver that might work.  The Hiro modem uses the Agere/Lucent chipset and there appears to be no Linux drivers for it anywhere.

Still wanting a USB modem, I did a little more exhaustive research. I’ve found two USB modems that are advertised to work under Linux: the TrendNet TFM-561U and the US Robotics model 5637 modem.

The tendnet modem is $20 verses $41 for the USR, so I went with the Trendnet. Plus I saw one very short blurb that someone had the trendnet working on a RPI.

Note, the Trendnet modem ends up not having a speaker in it. I cannot verify if the USR has one or not. Fortunately, I don’t care for my project.

Before trying the modem on a Raspberry Pi, I tried it on a laptop running linux Mint just to make sure everything worked properly before moving on to the RPI.

I plugged in the modem, verified it was seen in dmesg, lsusb, and the /dev directory. I then used putty to connect to serial port /dev/ttyACM0 it connected perfect on the first try and I was typing AT commands (note that echo is turned off by default on this modem and there is an invisible ATE1 command that got echo running for me).

(Click on this pic to make it big enough to read)

usbModem-fig1

 Will the Modem Work on a Raspberry Pi?

I repeated the process, plugging the modem into my Raspberry Pi. The onboard power supply provided enough power to supply the modem.

Checking dmesg the modem is seen:

usbModem-fig2

Checking lsusb, the modem is there:

usbModem-fig3

and finally checking for the device:

usbModem-fig4

I couldn’t get putty to work properly with my RPI because I access it via VNC. Turns out minicom is installed on the RPI by default, so I used that by typing:

sudo minicom -d /dev/ttyACM0

It brought up the modem and I was able to enter AT commands:

usbModem-fig6

There you have it. Dial up modem access for a Raspberry Pi.

Posted in c-rpi | Tagged | 6 Comments

ESP8266 Echos AT but will not Respond with OK

(click here to see index of all ESP8266 posts)

I’ve been playing with the ESP8266 a little for the past week and will shortly start posting some stuff, but the first head scratcher I ran across which I still have not seen documentation on is this:

You get the ESP8266 connected to your PC via an FTDI cable. When you type AT, it properly echos ‘AT’ back at you. But when you press ENTER (<CR>) you do not get an OK response.

Unlike anything else I’ve used in the past that uses the AT command set, control-M a.k.a. ENTER a.k.a carriage return (<CR>) is not enough. You must then press control-j (line feed).

So if you type AT<control-m><control-j> you should get an OK. At least I did.

In my terminal emulator of choice (an ancient copy of WRQ’s Reflections), there is a mode called AUTO LF. If I turn that on, then any time I press control-m, the sequence <control-m><control-j> is sent, and that solves the problem for me.

esp8266-crlf-fig1

I took a look at PUTTY, the only other serial port terminal emulator I ever use and while it has an option that seems that it would do an auto lf, it does not work for me.

esp8266-crlf-fig3

So with PUTTY, I still have to type control-m control-j to terminate each AT command.

 

 

Posted in c-esp8266 | Tagged | 5 Comments

Sunrise / Sunset Algorithm Implemented in Free Pascal / Lazarus

I needed to know sunrise / sunset times and wasn’t happy with any Pascal implementations I found. This code was implemented using the algorithm found at

http://williams.best.vwh.net/sunrise_sunset_algorithm.htm

http://web.archive.org/web/20160315083337/http://williams.best.vwh.net/sunrise_sunset_algorithm.htm

This is a simple unit that can be easily implemented. There are no O/S restrictions (that I know of), so it should work anywhere. I’ve run it on Windows and Raspberry Pi platforms successfully.

The call is:

time := sunRiseSet(sunMode, date, latitude, longitude, zenithMode, localOffset);

Where sunmode is

    sunrising                   = 0;
    sunsetting                  = 1;

Date is the date in question.

latitude,longitude are the fractional coordinates of the location in question.

ZenithMode is

    zenithOfficial              = 0;
    zenithCivil                 = 1;
    zenithNautical              = 2;
    zenithAstronomical          = 3;

and localOffset is the adjustment to convert the time from UTC time to local time (example -8 for US, West Coast).

unit sunRiseSetUnit;

{$mode objfpc}{$H+}{$R+}{$I+}

//-----------------------------------------------------------------------------
//
//  Sunrise/Sunset Time module
//
// 1.0 Apr 2015:
//      Original Version:
//
// ----------------------------------------------------------------------------

interface

uses
    classes,
    dateUtils;

function sunRiseSet(
    sunMode                     : integer;
    date                        : TDateTime;
    latitude                    : double;
    longitude                   : double;
    zenithMode                  : integer;
    localOffset                 : real
    )                           : TDateTime;

// ----------------------------------------------------------------------------

implementation

uses
    math,
    sysUtils;

function sunRiseSet(
    sunMode                     : integer;
    date                        : TDateTime;
    latitude                    : double;
    longitude                   : double;
    zenithMode                  : integer;
    localOffset                 : real
    )                           : TDateTime;

const
    sunrising                   = 0;
    sunsetting                  = 1;

    zenithOfficial              = 0;
    zenithCivil                 = 1;
    zenithNautical              = 2;
    zenithAstronomical          = 3;

    zenithDeg                   : array [0 .. 3] of double = (
                                    90.833333,
                                    96.0,
                                    102.0,
                                    108.0
                                    );

var
    cosDec                      : double;
    cosH                        : double;
    day                         : integer;
    h                           : double;
    l                           : double;
    lQuadrant                   : double;
    lngHour                     : double;
    m                           : double;
    month                       : integer;
    n                           : integer;
    n1                          : integer;
    n2                          : integer;
    n3                          : integer;
    oldDateSeparator            : char;
    oldShortDateFormat          : string;
    ra                          : double;
    raQuadrant                  : double;
    sinDec                      : double;
    t                           : double;
    tLocal                      : double;
    tLocalMean                  : double;
    tUTC                        : double;
    year                        : integer;

    // the algorith requires degrees NOT radians. These functions are
    // wrappers for the various trig functions which convert degrees to radians
    function degACOS(
            n                   : double
            )                   : double;
    begin
    degACOS := (180/pi)*arccos(n);
    end; // degACOS
    function degASIN(
            n                   : double
            )                   : double;
    begin
    degASIN := (180/pi)*arcsin(n);
    end; // degASIN
    function degATAN(
            n                   : double
            )                   : double;
    begin
    degATAN := (180/pi)*arctan(n);
    end; // degATAN
    function degCOS(
            angle               : double
            )                   : double;
    begin
    degCOS := cos((pi/180)*angle);
    end; // degCOS
    function degSIN(
            angle               : double
            )                   : double;
    begin
    degSin := sin((pi/180)*angle);
    end; // degSIN
    function degTAN(
            angle               : double
            )                   : double;
    begin
    degTAN := tan((pi/180)*angle);
    end; //degTAN

begin

if (not(sunMode in [0,1])) then begin
    writeln('sunMode must be 0-1.');
    halt(1);
    end;
if (latitude < -90) or (latitude > 90) then begin
    writeln('latitude outside of -90-90 range.');
    halt(1);
    end;
if (longitude < -180) or (longitude > 180) then begin
    writeln('longitude outside of -180-180 range.');
    halt(1);
    end;
if (not(zenithMode in [0..4])) then begin
    writeln('zenithMode must be 0..3.');
    halt(1);
    end;

month   := monthof(date);
day     := dayof(date);
year    := yearof(date);

// Calc day of year
n1  := floor(275 * month / 9);
n2  := floor((month + 9) / 12);
n3  := (1 + floor((year - 4 * floor(year / 4) + 2) / 3));
n   := n1 - (n2 * n3) + day - 30;

// Convert longitude to hour and calc approximate time
lngHour := longitude / 15;

if sunMode = sunRising then
    t := n + ((6 - lngHour) / 24)
else
    t := n + ((18 - lngHour) / 24);

// Calc the Sun's Mean anomaly
m := (0.9856 * t) - 3.289;

// Calc Sun's true longitude
l := m + (1.916 * degSIN(m)) + (0.020 * degSIN(2*M)) + 282.634;
if (l < 0) then
    l := l + 360
else if (l > 360) then
    l := l - 360;

// Calc the sun's right ascension
ra := degATAN(0.91764 * degTAN(L));
if (ra < 0) then
    ra := ra + 360
else if (ra > 360) then
    ra := ra - 360;

// Right ascension needs to be in the same quadrant as L
lQuadrant := (floor(l / 90)) * 90;
raQuadrant := (floor(ra / 90)) * 90;
ra := ra + (lQuadrant - raQuadrant);

// Convert Right ascension into hours
ra := ra / 15;

// Calc the Sun's declination
sinDec := 0.39782 * degSIN(l);
cosDec := degCOS(degASIN(sinDec));

// Calc the Sun's local hour angle
cosH := (degCOS(zenithDeg[zenithMode]) - (sinDec * degSIN(latitude))) /
            (cosDec * degCOS(latitude));
if (cosH > 1) then begin
    // Sun doesn't rise at this location on this date. We will just
    // set it to 12:00
    result := strToDateTime(format('%2d/%2d/%2d',[month, day, year]) + ' ' +
                '12:00');
    end
else if (cosH < -1) then begin
    result := strToDateTime(format('%2d/%2d/%2d',[month, day, year]) + ' ' +
                '12:00');
    end;

// Finish calculating H and convert into hours
if sunMode = sunRising then
    h := 360 - degACOS(cosH)
else
    h := degACOS(cosH);
h := h / 15;

// Calculate local mean time of rising/setting
tLocalMean := h + ra - (0.06571 * t) - 6.622;

// adjust back to UTC
tUTC   := tLocalMean - lngHour;

// adjust back to local time
tLocal := tUTC + localOffset;
if (tLocal < 0) then
    tLocal := tLocal + 24
else if (tLocal > 24) then
    tLocal := tLocal - 24;

// if minutes would round up to 60, go to next hour:
if (round((tLocal-floor(tLocal))*60) = 60) then
    tLocal := floor(tLocal) + 1;

oldShortDateFormat  := shortDateFormat;
oldDateSeparator    := dateSeparator;
shortDateFormat     := 'm/d/y';
dateSeparator       := '/';
result              := strToDateTime(format('%2D/%2D/%4D',[month, day, year]) + ' ' +
                        inttostr(floor(tLocal)) + ':' +
                        inttostr(round((tLocal-floor(tLocal))*60)));
shortDateFormat     := oldShortDateFormat;
dateSeparator       := oldDateSeparator;

end; //sunRiseSet

end.
Posted in c-lazarus, c-pcos | Tagged | 2 Comments