Category Archives: Analog

Analog Electronics

Analog Electronics RF Tindie Tools and Test Equipment

Just in! and the start on a VSWR bridge

I’ve been working on little bits over the last week or two, nothing notable but filling up my notebook with plenty of “lessons-learned”. For instance I decided I’m no good as estimating how many uH my home-made inductors are. I purchased a BK Precision 879B LCR meter to confirm that fact. A side-bonus was I went through all my caps and could test my home-brew ESR meter vs. the ESR meter built into the 879B and I now have a fair amount of capacitors that are going to the garbage. No more saving scrapped caps for me. I was working on an oscillator the other day.. well I winged the inductor.. not a wiggle out of the oscillator when finished, that’s what finally made me break down and buy the meter..

A crystal oscillator.. that doesn't oscillate
A crystal oscillator.. that doesn’t oscillate

Today I sat down at the bench and I started working on a project I have had on the board for a while (it’s a surprise); for this piece I made a 50 Ohm VSWR interface; then I threw it into a test jig and checked it out. It actually worked pretty solid. I got some 1 watt SMD resistors off an eBay purchased of some 49.9 ohm 0805 SMD resistors I ordered. The guy just randomly threw in 10 1-watt 49.9 ohm resistors… nice guy. I tested it up to 500MHz but after that I had a bit of noise measuring reverse power.. that’s okay though for me. Interestingly I found with my SA I have a pretty solid local noise source at 90.9, some local station I’m sure.  If you’re interested in making your own check out this guy’s website. He has a basic schematic of a bridge that is functionally equivalent to mine it seems. (a bridge with 3 resistors.. not a brain buster).

 

A little home made VSWR bridge for an upcoming project..
A little home made VSWR bridge for an upcoming project..

So after some success I decided it was time to get to mail. Yesterday I got a packages from the @tymkrs and Jason at AtomSoftTech.

Jason stuffed a box with some goodies I ordered and extras (thanks Jason!) The two most notable items of the bunch is the breadboard PIC buddy and the ESP8266 breakout board. The ESP board was flawless, but after use of BB PIC buddy I have ideas for v2. Now let me make it clear I saw this design before it went to the fab and I missed stuff that seems now obvious.. totally my bad.

Is it functional? Yep.. What would I recommend for changes?

Make the power side a little longer and have the USB jack coming in on the side.. if the PICKit2 is plugged in you can’t use the USB connector. Also while the PIC Kit 2 works okay I think pushing it a 1/2 inch away from the RJ12 jack for the ICD would make the insertion a little more solid. Nice product though.. this is certainly a new breadboard-fav. Jason is selling these for too cheap on Tindie. Get it before he gets smart and raises his price 🙂

The BB PIC Buddy and ESP8266 breakout board
The BB PIC Buddy and ESP8266 breakout board

There are some other items from AST as well but I’ll mention them later on. I had purchased two items from the @tymkrs ; the new Analog Shift Kit and the new SMD LM386 audio amplifier “Amplify Me”. The Amplify Me board works as expected, I checked out the PDIP version of this some time back ago, I’m not going to hunt for the post though, it’s a LM386 audio amp, kind of a no-brainer. I though of one change for future versions of this product that might have been a little more user friendly. It’d be nice if they made the product just a few more tenths of inches wide and brought that PCB 3.5mm jack out away and further back (back in reference to the photo below). I would make the jack so that it was level with a panel if you mounted the potentiometer into a panel. I don’t think it would add too much to board coast but it wold make this much easier to integrate into projects. As it is though, the potentiometer doesn’t have to be soldered into the board (it doesn’t come soldered) so it would be easier enough to work around. I still find it shocking to get a battery included in an order! It’s the little things @tymkrs!

Updated @tymkrs SMD LM386 Amplify Me
Updated @tymkrs SMD LM386 Amplify Me

No time to get to the Analog Shift kit today, I’ll save that for the future.

I have a lot more Analog bits I’m working on in the near future; I hope to get some of them mentioned here.

Analog Electronics Radio RF

Amidon Toriod Experimenter Kits

I have been pushing myself to build some IF filters. I’ve never built a front end of a radio; VCO, mixer, filters.. none of it. I started by buying the Amidon Toroid Experimenters kit #2 and #3 as many of the ARRL handbook samples use Amidon part numbers. I ended up switching to another book to do all my research though; “Secrets of RF Design”. Let me let you in on the secret.. it’s a lot of reading, not all of it stimulating. I also bought the “Island Cutter” from QRPme which is probably one of my favorite purchases of the year… armed with that I started building circuits.

If you’re working about purchasing the Amidon Experimenter Kits.. well I have no regrets. It gave me a good selection of options and even some larger one’s I don’t know when I will use but maybe for a switching supply project or something. I ordered a few other small pieces I knew I’d need more than 4 of just to have them on hand.

Amidon Toroid Kits

I really enjoy the circuits around varactor diodes. I’m building an analog front end but for stability I might just end up wwitching to DDS later on but for now for the VCO is a tank circuit. Next step is the mixer..

Varactor Tank Circuit Fun

 

I probably should still be working on other things, I have a pile of “to-do”s but I needed a little inspiration to keep me at the bench after all this summer fun. My last summer outing is a 7 day backpacking trip in the northern cascades packrafting! That’ll be some seriously needed unplug time. So stay tuned… I ordered about ~$500 worth of electronics for all my up-coming fun.. looking forward to digging into it. I still need to buy an LCR meter, I’ve never owned one and it would be nice to know my inductors is/are “in the ball field” when I wind something using the tables… I can do the math but I think it’d still be nice for a confirmation before I start soldering and making measurements.

Analog Electronics Radio

Vacation Tidbits

I’ve returned from vacation and brought back a ton of tidbits to share over the next few weeks.

I left the beautiful Pacific Northwest to work on my ranch house in Meade County, South Dakota. I had a number of projects I hoped to complete while there and got through a fair portion of my list that was mostly filled with “wishful thinking” mini-projects. Not all of these are electronics based but bear with me, there are some items of interest.. no guarantee it’s you who is interested though 🙂 I also hit up an AM site with one of my best friends and scored some goodies!

Water: My artesian well has low flow, this isn’t crippling but it can be a hassle. I’ve installed a water tank with a float that allows the well to fill a tank through a 3/4″ in-ground sprinkler solenoid. When pressure drops and the well booster pump kicks on it sucks every bit of water it can including any air it can find out of a contentiously flowing drain into a stock tank a couple hundred feet down the line. Now I’ll have a reservoir to provide extra water on the fly and filter some slight sand in the water supply.

Pump and Water Tank in the basement
Pump and Water Tank in the basement

Sewer: I had a collapsed sewer line… talk about the shits! 😀 I thought this was about all I would get done on my vacation as I was going to have to hand dig the line.. it was about 12 wide, 5 foot down. Luck day, I had a good friend stop by and helped me out a bit… that took off a few minutes of rockin’ the shovel.

0198aeb478ff8d171bb83efe889e5a6d8550ffb0df

With all that work out of the way I had some time to meet up with a friend at an AM broadcast site while he was performing some maintenance. I used to apprentice under him but ended up going a different career route. Not sure I made the right choice some days?

I grabbed my Rigol spectrum analyzer (you bring yours with you on vaca as well, right?) and threw a piece of wire into the input about a hundred feet away from the tower… the station is on 810KHz AM.

 

KBHB_wide

marker was obviously not on the peak on the reading above.

KBHB_2

I took a ton of readings, compared mine to a much more expensive SA (very satisfied with the results) as well as taking some readings on a 948MHz STL transmitter.

I scored a nice directional sampling line and a bunch of SMA connectors with coax, a 20 watt digital OTA cable transmitter and a ton of other little goodies while I was at it. I great score. I got a VCXO, some filters, attenuators and just a ton of stuff I’ll check out here and there.

0146ba8c3dea244962dd8398f1370519501a121397

AM Antenna

AM Transmitter

Finally, I’ve got some video to edit and drop on the YouTube channel as well but I’ll get to that in the coming days.

Analog Electronics

W0PCE ESR Meter Kit Build

In the Sept – Oct 13 ARRL publication of QEX, W0PCE has a nice article on ESR (Equivalent Series Resistance) meters. I won’t go into details because I did on a blog post I have saved in drafts for when I finish my own ESR meter but the one sentence version; An ESR meter tests electrolytic capacitors. This meter is a nice analog ESR meter that works well if you are just looking for a good/no-good meter reading.

A friend of mine when in on a buy from FAR circuits to get the board. I believe I reviewed this earlier? If not it’s in my ESR post.. so that’ll come.  The board was dirt cheap but if you’re particular you might be better off using protoboard. I don’t know where they got the parts package, but it all worked and came with everything except the connector, meter and battery pack.

 

ESR Meter

Shown is a 33 Ohm resistor for testing to see that 33 Ohms is nearly-full scale which is about perfect for me. I went with a BNC connector and cable… just because I have a ton of them. It’ll be hard to finish my updated ESR meter now that I have this but I’ll find the inspiration some time. 😀

Analog C Electronics Microcontrollers PIC Programming Steppers

Analog Stepper Gauge Friday night fun

Took a while to clear off the bench tonight. I got a little happy with the ORDER button last week through weekend. I’ve filled two more parts storage containers and luckily one of my new packages with another parts storage container from Amazon; I couldn’t find any locally, I hope they’re still making them.

The last thing I got to was this “Gauge Stepper Breakout” I got off The Rengineer (The Renaissance Engineer)’s Tindie store. Adam took this very nice stepper motor, put a gauge needle on it (which I believe he 3D printed, or at least it looks like it) and some nice diodes for voltage protection. What’s great about this board is you can drive it right from your microcontroller. I’m sure I don’t need to tell you how weird that is.. I worry about big LEDs.. but here this stepper was happy as a clam being powered by my PIC. I still might consider at least buffering this if I was to place it in a permanent  circuit.

Adam’s provides links to some Arduino libraries but he was saved me a ton of time and just happened to have some PIC sample code! Not before I had about 75% of a ECCP program completed. (I’ll link some of that code if you’re looking for an example of Enhanced PWM output). Once I had Adam’s code I ported it to the TAUTIC 18F26K22 dev board because I already had one on the breadboard. That was mostly changes in the TMR0 (timer 0) code. The only thing of note is check out my IO comments for wiring. You have to cook up 5V/GND to this board then I drove RC3 –> A1 RC2 — A2, RC1 –> B1 and RC0 –> B2. When I had it flipped around the stepper moved in the opposite direction of how I wanted.

A little video of the code in action:

This code is a little sloppy but I just testing this out and it did the trick:


/*
 * File:   main.c
 * Author: Charles M Douvier  Contact at: http://iradan.com
 * Core Driver Code by Adam F. of http://www.therengineer.com/
 *
 * Created on April 4th, 2014
 *
 * Target Device:
 * TAUTIC PIC 18F26K22 Dev Board
 *
 * Project:
 *
 *
 * Version:
 * 1.0
 *
 */

#ifndef _XTAL_FREQ
#define _XTAL_FREQ 4000000 //4Mhz FRC internal osc
#define __delay_us(x) _delay((unsigned long)((x)*(_XTAL_FREQ/4000000.0)))
#define __delay_ms(x) _delay((unsigned long)((x)*(_XTAL_FREQ/4000.0)))
#endif

#include 
#include 
#include 
#include 

//config bits
#pragma config FOSC=INTIO67, WDTEN=OFF, PWRTEN=OFF, CP0=OFF, CP1=OFF, BOREN=ON
#pragma config STVREN=ON, LVP=OFF, HFOFST=OFF, IESO=OFF, FCMEN=OFF

//WRT=OFF, FOSC=INTOSC, MCLRE=ON

#define _XTAL_FREQ 4000000 //defined for delay
#define MIN_STEPS_LEFT 23
#define MAX_ACCEL_INDEX 6
#define MAX_STEP 945 /* motor can move 945 steps from stop to stop*/

    int     an8_value, an9_value;          //value for a/d
    char    buf[10];            //buff for iota
    long int    fvar;           //long for format math
    long int    tens;           //left of decm
    long int    decm;           //decimal places
    int     tempi;              //to add leadign zeros..
    int     vtxdata;             //volts int for TX
    int     itxdata;

    unsigned short defaultAccelTable[][2] =
{
  {   1750, 3},
  {   1149, 3},
  {  926,   3},
  {  794,   3},
  {  709,   3},
  {  666,   4},
  {  /*629*/450,   4},
};
unsigned int currentStep;
unsigned char currentState;
unsigned char stateMap[] = {0x09, 0x01, 0x07, 0x06, 0x0E, 0x08};
unsigned char serialBuffer[10];
unsigned char serialByteCount;
 static const unsigned char stateCount = 6;

    volatile unsigned int uart_data;    // use 'volatile' qualifer as this is changed in ISR
/*
 *
 */
void interrupt ISR() {

    if (PIR1bits.RCIF)          // see if interrupt caused by incoming data
    {
        uart_data = RCREG;     // read the incoming data
        PIR1bits.RCIF = 0;      // clear interrupt flag
    }

}

void init_io(void) {
    TRISAbits.TRISA0 = 0; // output
    TRISAbits.TRISA1 = 0; // output
    TRISAbits.TRISA2 = 0; // output
    TRISAbits.TRISA3 = 0; // output
    TRISAbits.TRISA4 = 0; // output
    TRISAbits.TRISA5 = 0; // output
    TRISAbits.TRISA6 = 0; // output
    TRISAbits.TRISA7 = 0; // output

    ANSELA = 0x00; // all port A pins are digital I/O

    LATAbits.LATA0 = 0;
    PORTAbits.RA0 = 0;

    TRISBbits.TRISB1 = 0;   //P1C output
    TRISBbits.TRISB2 = 0;  // P1B output
    TRISBbits.TRISB3 = 1;  // AN9    speed control 0-5V
    TRISBbits.TRISB4 = 0;  // P1D output
    TRISBbits.TRISB5 = 1; // RB5 = nc
    TRISBbits.TRISB6 = 0; // RB6 = nc
    TRISBbits.TRISB7 = 0; // RB7 = nc

    ANSELB = 0b00001000;     //RB3, AN9

    TRISCbits.TRISC0 = 0; // output to B2 .. reversed to stoke the right direction
    TRISCbits.TRISC1 = 0; // output to B1
    TRISCbits.TRISC2 = 0; // output to A2
    TRISCbits.TRISC3 = 0; // output to A1
    TRISCbits.TRISC4 = 0; // output
    TRISCbits.TRISC5 = 0; // output
    TRISCbits.TRISC6 = 0; // output
    TRISCbits.TRISC7 = 0; // output
    ANSELC = 0x00; // all port B pins are digital I/O
}

void uart_xmit(unsigned int mydata_byte) {

    while(!TXSTA1bits.TRMT);    // make sure buffer full bit is high before transmitting
    TXREG = mydata_byte;       // transmit data
}

void serial_init(void)
{
    //9600 8N1
    // calculate values of SPBRGL and SPBRGH based on the desired baud rate
    //
    // For 8 bit Async mode with BRGH=0: Desired Baud rate = Fosc/64([SPBRGH:SPBRGL]+1)
    // For 8 bit Async mode with BRGH=1: Desired Baud rate = Fosc/16([SPBRGH:SPBRGL]+1)

    TXSTA1bits.BRGH=1;       // select low speed Baud Rate (see baud rate calcs below)
    TXSTA1bits.TX9=0;        // select 8 data bits
    TXSTA1bits.TXEN = 1;     // enable transmit

    RCSTA1bits.SPEN=1;       // serial port is enabled
    RCSTA1bits.RX9=0;        // select 8 data bits
    RCSTA1bits.CREN=1;       // receive enabled

    SPBRG1=25;  // here is calculated value of SPBRGH and SPBRGL
    SPBRGH1=0;

    PIR1bits.RCIF=0;        // make sure receive interrupt flag is clear
    PIE1bits.RCIE=1;        // enable UART Receive interrupt
    INTCONbits.PEIE = 1;    // Enable peripheral interrupt
    INTCONbits.GIE = 1;     // enable global interrupt

         __delay_ms(50);        // give time for voltage levels on board to settle

    uart_xmit('R');         // transmit some data
}

// All this motor and timer code is from Adam with very minor changes to fit the processor

void t0Delay(unsigned int usec)
{
    unsigned int t0ticks; //16 microsecond timer0 ticks
    unsigned char t0Preload;
    if(usec<16)
    {
        t0ticks=1;
    }
    else
    {
        t0ticks = usec/16;
    }
    t0Preload = 0xFF - t0ticks;
    INTCONbits.TMR0IF=0; //clear the flag
    TMR0 = t0Preload;
    while(INTCONbits.TMR0IF==0)
    {
        ;
    }
}

void zeroMotor()
{
    unsigned int i;
    for (i=0; i < MAX_STEP; i++)
    {
        LATC=stateMap[currentState];
        currentState = (currentState + 5) % stateCount;
        t0Delay(1900);  //2200 in datasheet
    }
    //now the motor is zeroed, reset our state variables.
    currentStep = 0;
    currentState = 0;
    LATC=0; //turn off coils
}

void moveMotor(unsigned int targetStep)
{
    unsigned int dir;
    unsigned int curDelay;
    unsigned char speedIndex=0;
    unsigned char stepsAtThisSpeed=0;
    unsigned int stepsLeft;
    if(currentStep<targetStep)     {         dir = 1;         stepsLeft = targetStep-currentStep;     }     else     {         dir = -1;         stepsLeft = currentStep - targetStep;     }     while(stepsLeft>0)
    {
        if(stepsLeft<=MIN_STEPS_LEFT)         {             //decellerating             if(stepsAtThisSpeed==0)             {                 if(speedIndex>0)
                    speedIndex--;
                curDelay=defaultAccelTable[speedIndex][0];
                stepsAtThisSpeed=defaultAccelTable[speedIndex][1];
            }
        }
        else
        {

            //accellerating or steady state
            if(stepsAtThisSpeed==0)
            {
                if(speedIndex<MAX_ACCEL_INDEX)                 {                     speedIndex++;                     curDelay=defaultAccelTable[speedIndex][0];                     stepsAtThisSpeed=defaultAccelTable[speedIndex][1];                 }                 //else we're at steady state - do nothing.             }         }         //write step         LATC=stateMap[currentState];         if(dir==1)         {             currentState = (currentState + 1) % stateCount;         }         else         {             currentState = (currentState + 5) % stateCount;         }         t0Delay(curDelay);         if(stepsAtThisSpeed>0)
        {
            stepsAtThisSpeed--;
        }
        stepsLeft--;
        currentStep+=dir;
    }
}

int main(void) {

    init_io();
    serial_init();

    // set up oscillator control register, using internal OSC at 4MHz.
    OSCCONbits.IRCF = 0x05; //set OSCCON IRCF bits to select OSC frequency 4MHz
    OSCCONbits.SCS = 0x02; //set the SCS bits to select internal oscillator block

    ADCON0 = 0b00100101;                            //select AN9 and enable
    ADCON1 = 0b00000000;                  //speed Vref=AVdd, VssRef=AVss
    ADCON2 = 0b00111011;                //ledft justified, 20RAD, FRC

    INTCONbits.TMR0IE = 0;

    TMR0=0;

    T0CONbits.T08BIT = 1;
    T0CONbits.T0CS = 0;
    T0CONbits.PSA = 0;
    T0CONbits.T0PS = 0x04;
    INTCONbits.TMR0IF = 0;

        T0CONbits.TMR0ON = 1;

    __delay_us(5);

    currentStep = 0;
    currentState = 0;

    zeroMotor();         
    __delay_ms(149);        //this could be less messy
    __delay_ms(149);
    __delay_ms(149);
    __delay_ms(149);
    __delay_ms(149);
    __delay_ms(149);
    moveMotor(20);
    __delay_ms(149);
    __delay_ms(149);
    __delay_ms(149);
    __delay_ms(149);
    __delay_ms(149);
    __delay_ms(149);

    moveMotor(940);
    moveMotor(5);

    while (1) {

        //PORTAbits.RA0 = 1;      //heart beat
        //__delay_ms(50);
        //PORTAbits.RA0 = 0;
        //__delay_ms(50);

        ADCON0 = 0b00100101;    //select AN9 and enable
        __delay_us(5);
        GO = 1;
        while (GO) continue;    //wait for conversion
        an9_value = ADRESH;     //AN9 value

        fvar = an9_value;
        fvar = fvar * 10749;    //calibration.. change to meet your needs
        fvar = fvar / 256;
        tens = fvar / 100;
        //tens = tens % 10;
        decm = fvar % 100;
        vtxdata = fvar / 20;
        uart_xmit(vtxdata);    // -->RS232

        moveMotor(vtxdata);
        //moveMotor(5); //from sample code
    }
    return (EXIT_SUCCESS);
}

Some ECCP ( Enchanced PWM ) code written for the PIC 18F26K22 code I wrote following the screen shot of the output:

Deadband on Enhance PWM mode output on PIC
Deadband on Enhance PWM mode output on PIC

void pwm_init(){

//    CCPR1L = 0x120;
    CCPR1Lbits.CCPR1L = 0xFE;
    PR2 = 0xFE;
    CCPTMRS0bits.C1TSEL = 0;     //CCP TMR2 Selection
    CCP1CONbits.P1M = 0x02;     //half bridge
    CCP1CONbits.DC1B = 0x00;
    PWM1CONbits.P1RSEN = 0;
    PWM1CONbits.P1DC = 0x1F;    //dead band delay
    ECCP1ASbits.CCP1AS = 0x00;
    ECCP1ASbits.CCP1ASE = 0;    //Auto-shutdown off
    CCP1CONbits.CCP1M = 0x0C;
    PSTR1CONbits.STR1A = 1;
    PSTR1CONbits.STR1B = 1;

    T2CONbits.T2CKPS = 1;
    T2CONbits.TMR2ON = 1;

}

//.. now dump something smaller than 127 into CCPR1Lbits.CCPR1L
//to set the pulse width
Analog Electronics

The Hackers Bench Tone Sequencer

@JohnS_AZ shared his beautiful schematic of a tone sequencer [PDF] he designed with me a few weeks ago. I think he designed it for the @tymkrs ? I watched the video and it looked like a fun project, I wasn’t wrong!

John’s webpage is at : http://hackersbench.com/

I was shooting for sticking this project into an Altoids tin .. I had low expectations which is good because I’m about 1 cm t0 tall on the trimmers. If I found some lower profile parts and removed my DIP sockets I could pull this off. I’m not that motivated to take care of it but if you want to try you know what to do 😉 I used the Adafruit Altoids tin PCB… I purchased a couple of these a while back; they’re good stuff. The oscillator is up on the top board and then ‘LS90, 4051, VCO and the audio amp are below. I am particularly impressed with John’s use of the Pin 5 input on the LM555 to use it as a VCO; I haven’t seen this done much, usually you’re sticking a cap to ground on this input or letting it float (gasp!). I just have to add some stand-offs and a couple connectors and this project is wrapped up.
My version of his circuit:

Yep, just a little to "thick" to fit in the can... oh well. Stand off's will work :)
Yep, just a little to “thick” to fit in the can… oh well. Stand off’s will work 🙂

 

John made two great videos of this project:

 

Analog Electronics PIC Test Equipment

An evening of measuring inductance

I was inspired by Alan Wolke’s ( @W2AEW ) video on measuring capacitors and inductors with an oscilloscope. I tried it out and it works pretty reasonably; yeah why wouldn’t it? Anyhow, if you can do it on an oscilloscope it can be done by a microcontroller right?  I have been trying to keep myself from buying this $220 eBay LCR meter on eBay.. it looks nice enough (model: MCH2811C). I needed to make this a project or I was going to pull the trigger on some Chinese garbage!

I went with simple and cheap, I don’t know how well it’ll work out yet but I bread-boarded a proof of concept design. It tested okay after some modification. The first road bump was I had found the PIC output pins had unacceptable rise time compared to 74HC14. The first change was using the PIC output to drive the 74HC14 HEX inverter to get the quick rise time needed.  I’m throwing a fast edge at the tank circuit that includes an “unknown” inductor and then I do my measurement, just as Alan used his homebrew TDR circuit. I went really low tech on my measurement circuit, I may change this. I used an LM339 comparator and a trimmer as a voltage divider. The first couple waves in the tank “ring” trigger the comparator and I measure the frequency by figuring out the time between the positive pulses by timer. Pretty simple no? It works fine as it turns out. I will have to get a better capacitor and ensure I measure it very accurately to do my math in the PIC and get a reasonable result.

Instead of the usual photos I made another YouTube video. It wasn’t a great one, one take, no editing.. it’s gets my point across (kind of).

My project proof of concept for the PIC L-meter. With the addition of a known inductor and a rotary switch and a little more code you can turn this into a PIC LC-meter in no time.

 

Analog C Electronics Microcontrollers PIC Programming

Testing an LCD with the PIC 16F1509 and the XC8 compiler

Nuts and Volts, January 2014 had an article named “The (Nearly) Universal Process Monitor”. The whole magazine had a number of Microchip PIC based articles which is rare these days, as the articles win out to other platforms such as MSP430, Propeller, and Arduino. The article is a pretty nice project but I went to download the code and it’s just a HEX file. Lame! I’ve been guilty of this and I promise never to do it again.

If you’re as disenchanted with building something without modifiable code as I am here is a starting block! I don’t normally program in C but I’m trying to force myself so I can get better. You can trim down many timing delays, and certainly shouldn’t be a problem to optimize my code as I made no effort to do so myself.

LCD+A/D test on the PIC

 

When writing the A/D math for this I found some interesting issues; here is one of those: (in pseudo code)

int_Var1 = 8-bit A/D conversion
long_int_Var2 = int_Var1 * 5000

given int_Var1 = 17  long_int_Var2 should equal 85000 but it didn’t; It came out 19,464 (roll over from 65,536).

However:

long_int_Var2 = int_Var1
long_int_Var2 = long_int_Var2 * 5000  //works like a charm.

Weird? I tried this in an ANSI C compiler and the first equation worked okay; I guess this is just a quirk about XC8. I somewhat understand why it would act that way and caught it quick but it could easily have been a difficult bug to hunt down.

There is obviously not the greatest amount of resolution in an 8-bit conversion but I was really just testing an LCD I just got off eBay and through this would be a fun way to do so, work on my C skills, and help out anyone wanting a head-start on building their own metering application. If you don’t want to do the math yourself you’ll find you get about 20mV/step resolution (5000mV/256) at 8-bit.

 

The thousands position is moot and could be dropped. The resolution of the A/D being used in 8-bit doesn't allow for reliable usage in the thousandths.
The thousands position is moot and could be dropped. The resolution of the A/D being used in 8-bit doesn’t allow for reliable usage in the thousandths.

 

Notes: Refresh is slow, clearing the LCD line #2 is slow because I didn’t like the flash of clearing the whole display… it could have also been made more quick had I not written 16 spaces and just written enough to cover my 7 digits of output. I also should have dropped the LSB of my number because it’s a worthless bit considering my resolution. I will if this gets used on anything other than a breadboard test.

I used a standard 44780 16×2 LCD, a Tautic development board, and a PIC 16F1509 (happens to come with the dev board). For programming I used MPLAB X IDE v1.95 and XC8 v1.21 (free version) and the PICkit 3 programmer. The code is commented enough to figure out the hardware setup.

code (with whatever fixes since wiring the blog) can be found at : https://github.com/chasxmd/iradan.com-2014

at writing it looks like:

/* 
 * File: main.c
 * Author: Charles M Douvier
 * Contact at: http://iradan.com
 *
 * Created on January 18, 2014, 9:42 AM
 *
 * Target Device:
 * 16F1509 on Tautic 20 pin dev board
 *
 * Project:
 * A/D --> LCD Test
 * 8-bit resolution across Vdd to Vref (0-5V)
 * for 3.3V operation adjust A/D math
 *
 * LCD (44780 type) Test with XC8 compiler
 * LCD code ported from Mike Pearce's 2001 LCD code for HI-TECH C
 * as found on http://www.microchipc.com/
 */
#include <xc.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <plib.h>
//config bits
#pragma config FOSC=INTOSC, WDTE=OFF, PWRTE=OFF, MCLRE=ON, CP=OFF, BOREN=ON, CLKOUTEN=OFF, IESO=OFF, FCMEN=OFF
#pragma config WRT=OFF, STVREN=OFF, LVP=OFF
#define _XTAL_FREQ 4000000 //defined for delay
int an9_value; //value for a/d
 char buf[10]; //buff for iota
 long int fvar; //long for format math
 long int ones; //left of decm
 long int decm; //decimal places
 int tempi; //to add leadign zeros..
/*
 * LCD RS LATA.5
 * LCD EN LATA.4
 * LCD DATA4 LATC.0
 * LCD DATA5 LATC.1
 * LCD DATAT6 LATC.2
 * LCD DATA7 LATC.3
 * LED LATA.0 for scan rate/heartbeat
 */
void lcd_strobe (void) //TOGGLE LCD_EN
{
 LATAbits.LATA4 = 0;
 __delay_ms(20);
 LATAbits.LATA4 = 1;
}
/* write a byte to the LCD in 4 bit mode */
void lcd_write(unsigned char c)
{
 LATC = c >> 4;
 lcd_strobe();
 LATC = c;
 lcd_strobe();
 __delay_us(100);
}
/*
 * Clear and home the LCD
 */
void lcd_clear(void)
{
 LATAbits.LATA5 = 0;
 lcd_write(0x1);
 __delay_ms(2);
}
/* write a string of chars to the LCD */
void lcd_puts(const char * s)
{
 LATAbits.LATA5 = 1; // write characters
 while(*s)
 lcd_write(*s++);
}
/*
 * Go to the specified position
 */
void lcd_goto(unsigned char pos)
{
 LATAbits.LATA5 = 0;
 lcd_write(0x80+pos);
}
/*
 * Write 16 spaces on LCD 2 to avoid blanking, (ugly CLEAR effect)
 * this is slow but work for my needs
 */
void lcd_clrline2(void)
{
 lcd_goto(40);
 lcd_puts(" ");
 lcd_goto(40);
}
/* initialise the LCD - put into 4 bit mode */
void lcd_init(void)
{
 LATAbits.LATA5 = 0; // write control bytes
 LATC = 0x03;
 __delay_ms(150); //power on delay
 lcd_strobe();
 __delay_ms(5);
 lcd_strobe();
 __delay_ms(5);
 lcd_strobe();
 __delay_ms(5);
 LATC = 0x02; // set 4 bit mode
 __delay_ms(5);
 lcd_strobe();
 __delay_ms(5);
 lcd_write(0x28); // 4 bit mode, 1/16 duty, 5x8 font
 lcd_write(0x08); // display off
 lcd_write(0x0C); // display on cursor+blink off
 lcd_write(0x06); // entry mode
}
int main(void) {
 // set up oscillator control register, using internal OSC at 4MHz.
 OSCCONbits.IRCF = 0x0d; //set OSCCON IRCF bits to select OSC frequency 4MHz
 OSCCONbits.SCS = 0x02; //set the SCS bits to select internal oscillator block
TRISCbits.TRISC0 = 0; // output
 TRISCbits.TRISC1 = 0; // output
 TRISCbits.TRISC2 = 0; // output
 TRISCbits.TRISC3 = 0; // output
 TRISAbits.TRISA0 = 0; // output
 TRISAbits.TRISA4 = 0; // output
 TRISAbits.TRISA5 = 0; // output
 TRISCbits.TRISC7 = 1; //analog input
 ANSELCbits.ANSC7 = 1; //...setup on PORTC.7/AN9
 LATAbits.LATA0 = 0; //LED Im-Alive test
__delay_ms(250); //let the power settle
lcd_init();
 __delay_ms(10);
 lcd_clear();
//display test message
 lcd_puts("Testing the LCD.");
 lcd_goto(40);
ADCON0 = 0b00100101; //select AN9 and enable
/* ADCON1
 * bit 7 ADFM: ADC Result Format Select bit
 * 0 = Left justified. Six Least Significant bits of ADRESL are set to ?0? when the conversion result is loaded.
 * bit 6-4 ADCS<2:0>: ADC Conversion Clock Select bits
 * 110 = FOSC/64
 * bit 3-2 Unimplemented: Read as ?0?
 * bit 1-0 ADPREF<1:0>: ADC Positive Voltage Reference Configuration bits
 * 00 = VREF+ is connected to VDD
 */
 ADCON1 = 0b01100000; //left justified, FOSC/64 speed Vref=Vdd
while(1)
 {
 LATAbits.LATA0 = 0; //debugging

 lcd_clrline2(); //clear LCD line 2 by writting " " and return
__delay_us(5); 
 GO = 1;
 while (GO) continue; //wait for conversion
 an9_value = ADRESH; //AN9 value
 //format value for LCD read out
 //value = AD_value * 5000 (because 5000mV is Vref)
 //value = value / 256 (8 bit number)
 fvar = an9_value;
 fvar = fvar * 5000;
 fvar = fvar / 256;
 ones = fvar / 1000;
 ones = ones % 10;
 decm = fvar % 1000;
LATAbits.LATA0 = 1; //LED Im-Alive test. I made it through conversion
//page 366 of XC8 user guide
 itoa(buf,ones,10); //int conv to buffer
 lcd_puts(buf); //outputs "1s" place to LCD.
 lcd_puts(".");
 //page 374 of XC8 user guide
 ltoa(buf,decm,10); //long conversion to buffer
 tempi=strlen(buf); //uh, adding leading zeros..
 tempi=3-tempi; //probably a better way of doing thing
 while (tempi) //first figure out how many zeros
 {
 lcd_puts("0"); //missed 3-string length
 tempi=tempi-1; //then send them until done
 }
 lcd_puts(buf); //output buffer to LCD
lcd_puts(" V"); //attach some units for display
 //delay
 __delay_ms(999); //LCD refresh rate
 }
 return (EXIT_SUCCESS);
}
Analog Electronics

MC1377 Memories

My first working circuit that I designed was based on the Motorola MC1377. It’s a RGB to NTSC encoder. I am pretty certain I actually still have the chip stored away in my linear/analog microchip parts storage. Apparently they are still available NOS on eBay. I can’t claim that I designed it myself; I’m certain my best friend of the time, Jason G., likely had assisted and designed some of the circuit. At the very least he had a lot of input. It was decades ago, who has that kind of memory? Jason had gotten me interested in “the best” computer of the time. The Amiga 500. I don’t know if it was the best home computer of the time but it certainly was in front of the pack. A powerfully Motorola 68000 and color computing when the 8088 just got 4-color CGA! The Amiga had been around for a while why I bought mine; Long enough for me to buy a refurbished A500 from a commodore shop in north Kent/Tukwila, WA. Jason stayed overnight and we stayed up until the single digits of the morning building this circuit because I had not  yet saved enough money to buy the A 1084S monitor… the time had come.. my carpet sporting an extra burn mark from a soldering iron. I was 15 or 16 at the time and I usually soldered on the floor, there were already a number of burn marks by then. We powered up the circuit and plugged it into the Amiga and then my TV… Success! Well kind of.. everything was very purple but the output was perfectly usable. The start of my love affair with Amiga computers and a further solidification of my primary hobby; electronics.

I’m off to LA for some training this week. Hopefully I get some programming done on my projects. I brought a small “go bag” of electronics for out-of-town work. Hopefully the TSA doesn’t give me too much trouble. I’m sure a bag of electronics is a scary thing for those who don’t know what they’re looking at.

Analog Electronics Hiking/Backpacking Microcontrollers

Wireless Plant Soil Monitoring: The Beginning.

I saw a little probe for monitoring soil on eBay.. $1.69 and free shipping.. purchased! Okay.. its a lame little PCB with some electronics I won’t use but still, nifty. I didn’t have much on my plate today and I was pretty sore from a solid hike yesterday so I was riding the bench seat today. I built a little front end circuit mated to a little MCU built on a Jayson Tautic 8 pin dev board with a 12F1840. It dumps serial out to a $3 433Mhz transmitter when the soil is low on water (still need to write some sleep code).. on the other side the receiver and well I don’t know yet. Honestly I started with thinking about a XPORT but I haven’t made my mind up.

Work in progress.... watching dirt dry.
Work in progress…. watching dirt dry.

 

So, a funny side effect: My wife was frustrated that she couldn’t get our wireless Christmas lights to turn on. Heh, well “Ooops!”… shocker, I had to turn my circuit off. So next I’ll work on the receiver side. I’m thinking my poor plants need to text message me when they’re thirsty? I’ll drop code later when it’s more complete.

And yesterday! I hiked past this pretty awesome frozen water fall (and two others) on my way up to Lake Serene. Last year we got stopped by a nasty avalanche field.. this year is was just solid ice. Thankfully I had my Kahtoolas.

forwa