So… I ordered a Spark Core…

… and these things are really neat.

Ok, so what is a Spark Core?   Wait…  lets start with the fact that this was a Kickstarter project that succeeded and is now a full fledged product that sadly I did not know about until afterwards.  I’d have been there supporting this Kickstarter if I had known about it. I tried to support a different but *very* similar Kickstarter project (well, not tried, I did support it) and have yet to see the product that is now many many months late. Now that I have the Spark core, and I like it, I’m pretty sure I won’t care when the Flutter *finally* arrives.

spark core image

spark core

 

So, back to what a Spark Core is.  It is a small device, roughly the size of an oversize collector edition US postage stamp.  It’s designed to fit into a Solder-less breadboard for easy project development and comes in 2 flavors… one with an on-board “chip” antenna and one with a small antenna jack that allows you to install your own wifi antenna… I grabbed an antenna out of my pile of broken wifi routers.  I wasn’t sure it would work… but seems to work just fine and uses the same RF jack (imagine that?).

For more information on what a Spark Core is, go here: Spark Core Getting Started

So what am I doing with it? Well, I’m learning what it can do first… and that’s a tiny bit tricky. The documentation is written more geek than noob friendly and while I have no issue with the documentation in general, it does seem to have some gaps here and there. I suppose with time this will all get better.

For example; they did make it seem like it would do some automagic things to get it quickly “registered” in the cloud and that my phone app could talk to it right away. No such luck. My Phone app never found the device and the status LED said I was happily connected. I needed to go through a rather manual process of attaching to the device in a serial debug mode to capture my unique ID to claim my core manually. Again, it was supposed to just work… but a quick check says I’m not the only one this happened to. (ed. I did acquire an additional spark core and the second one installed and connected and was claimed without a hiccup)

With that initial stumble out of the way… I needed to see how Arduino compatible this is so I started writing some code. As long as I stick to true Arduino’s abstract language (and not hardware dependent short cuts like you might find in some existing libraries) all is well. This device does not have an AVR MCU at it’s heart. It uses an STM32 MCU which is a much more capable device coupled with a TI CC3300 wifi in-a-box chip to create a complete arduino-like wifi device in a seriously small package.

My first project on the device after playing with examples is a simple “always correct” LED clock using the SparkFun 4 digit seven segment serial LED. It works… and displays the correct time as soon as it boots up with no need for battery backup or an RTC chip. The part number COM-11629. This is a mildly depressing LED display due to the fact that it is running on 3.3 volts and has 1000 Ohm current limiting resistors on the LED’s. (Did I mention that the Spark Core is a 3.3V device? No? oops.)

Seriously… 1000 Ohms at 3.3 volts is not the ideal value of the current limiting resistors. It should be around 47 Ohms… not 1000 Ohms. The end result is you can only really see the display in the dark.

2014-12-05 14.10.37

Anyway… the code part works… It uses built in features like wire library and time library that are already in the API. Here, see for yourself*…


//==============================================================================
//  III  2222   CCCC  CCCC L     OOOOO  CCCC K   K
//   I       2 C     C     L     O   O C     K  K
//   I    222  C     C     L     O   O C     KK
//   I   2     C     C     L     O   O C     K K
//  III  22222  CCCC  CCCC LLLLL OOOOO  CCCC K   K
//==============================================================================

//==============================================================================
// Program:      I2Cclock
// Author:       Pete Willard
// Version:      1.0
// Target:       SparkCore
// Date:         2014/12/04
// Time:         08:14:45
// Notes:

// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.

// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.

// You should have received a copy of the GNU General Public License
// along with this program.  If not, see <http://www.gnu.org/licenses/>.

//
// Reference:
//  Used rather sketchy Sparkfun serial LED display "datasheet"
//  Part #  COM-11629 - Note: it's a rather dim display.
//==============================================================================
 # define bitSet(value, bit)((value) |= (1UL << (bit)))
 # define bitClear(value, bit)((value) &= ~(1UL << (bit)))

//=====[ CONSTANTS ]============================================================
// # define DEBUG 0 // 0 = debugging disabled, 1 = enabled
//This is the default address of the OpenSegment with both solder jumpers open
 # define DISPLAY_ADDRESS1 0x71

// definitions from sparkfun for bitwise led controls (decimal/colon/dot)
 # define COLON 4
 # define DOT 5

// Time Sync and Time Zone settings
const int syncInterval = 60 * 60 * 8; //sync every  4 hours

static signed char const DEFAULT_TIME_ZONE = -4;

//=====[ VARIABLES ]============================================================
long millisTimer;
int lastSync = 0;
boolean colonOn = false;
boolean ampm = true;
char bits; // used to track binary values for bitwise

//=====[ SETUP ]================================================================
void setup() {


	Spark.connect();
	 while(Spark.connected() == false) {
	     delay(100);
	 } while(Time.year() == 1970)
	  {
	     Spark.syncTime();
	     Spark.process();
	     delay(100);
	  }
	 Spark.disconnect();
	 while (Spark.connected() == true) {
	     delay(100);
	     Time.zone(DEFAULT_TIME_ZONE);
	 }
	 
	Wire.begin(); // join i2c bus as master
	Wire.beginTransmission(DISPLAY_ADDRESS1); // transmit to slave device #4
	Wire.write('v');
	Wire.write(0x7A); // Brightness control command
	Wire.write(100); // Set brightness level: 0% to 100%
	Wire.endTransmission(); // stop transmitting

}

//=====[ MAIN PROCESS LOOP ]====================================================
void loop() {
	ampm = Time.isAM();
	showTime();
	delay(1000);
	adjustTime();
}

//==============================================================================
void adjustTime() {
	if (lastSync + syncInterval < Time.now()) {
		Spark.syncTime();
		lastSync = Time.now();
	}
}

//==============================================================================


//==============================================================================
//  Must be called after a "begin.transmission()" command.
//==============================================================================
void colonFlash() {
	//Blink the colon every other second

	if (colonOn == true) {
		colonOn = false;
		bitClear(bits, COLON);

	} else {
		colonOn = true;
		bitSet(bits, COLON);

	}
	Wire.write(0x77); // control command
	Wire.write(bits); // Turns on colon
}

//==============================================================================
//  Must be called after a "begin.transmission()" command.
//==============================================================================
void setPM() {
	if (ampm == true) {
		bitClear(bits, DOT);
	} else {
		bitSet(bits, DOT);
	}

	Wire.write(0x77); // control command
	Wire.write(bits); // Turns on colon

}

//==============================================================================
void showTime() {
	char out[] = {
		0,
		0,
		0,
		0
	}; // place holder for time array

	char hour = Time.hourFormat12();
	char min = Time.minute();

	sprintf(out, "%2d%02d", hour, min); // format current time into char array
	Wire.beginTransmission(DISPLAY_ADDRESS1); // begin I2C transmit to device

	setPM();
	colonFlash();

	for (byte x = 0; x < 4; x++)
		Wire.write(out[x]); //Send a character from the array out over I2C
	Wire.endTransmission(); //Stop I2C transmission

}


So, how does Serial.readBytesUntil() work?

I’ve been toying with the idea of setting the clock on my Arduino RTC (a DS3234 dead-on real time clock) because even though it still keeps good time, it’s still impacted by daylight savings time changes and because setting the time using a boot-loader based upload can be such a hit or miss sort of thing.

So, to accomplish this in as close to real-time as possible, I started thinking about how I could send commands to the arduino from Python code on my Raspberry Pi. I opted for a COMMAND,DATA structure to simplify parsing.

The goal is to keep it simple and to use a part of the serial library that I have not used yet: “Serial.readBytesUntil()” while avoiding the requirement to include “string.h” in my code. Why? Because I need this to be part of a larger program that already stretches the limits of available RAM on my UNO. The upside of using “readBytesUntil” is that you don’t have to keep checking the input buffer and assemble an array of char… the downside of using “readBytesUntil” is that it has a default timeout of 1 second. So how useful this is in the end remains to be fully tested.

Right now, there is no bounds checking… so if the command text is larger than 10 chars and data is larger than 15, you get “unpredictable” results.

Arduino Code:

 

//==============================================================================
// Program:      SerialParse.ino
// Author:       Pete Willard
// Version:      1.0
// Target:       UNO R3, IDE 1.03 
// Date:         2013/04/08
// Time:         09:47:54
// Notes:        
//               Uses Serial I/O
// Reference:    
//==============================================================================
 
//=====[ INCLUDE ]==============================================================
//#include <stdlib.h>
 
 
//=====[ CONSTANTS ]============================================================
#define   DEBUG   1   // 0 = debugging disabled, 1 = enabled
const int bSize = 20; 
 
//=====[ PINS ]=================================================================
int Led = 13;
 
//=====[ VARIABLES ]============================================================
 
    char Buffer[bSize];  // Serial buffer
        char Command[10];    // Arbitrary Value for command size
        char Data[15];       // ditto for data size
        int ByteCount;
 
//=====[ SUBROUTINES ]==========================================================
 
void SerialParser(void) {
//
//  One command per line.  Eventually, Data may have multiple 
//   fields separated by ":"
//  Command Format: "up to 5 Letter command, up to 10 letter data<\n>"
//                  No checking.
//
//  count will  be below Zero on a timeout.
//  read up to X chars or until EOT - in this case "\n" 
 ByteCount = -1;
 ByteCount =  Serial.readBytesUntil('\n',Buffer,bSize);  
 
   if (ByteCount  > 0) {
        strcpy(Command,strtok(Buffer,","));
                  
        strcpy(Data,strtok(NULL,","));             
   }
   memset(Buffer, 0, sizeof(Buffer));   // Clear contents of Buffer
   Serial.flush();
}
 
 
//=====[ SETUP ]================================================================
void setup() {
    Serial.begin(9600);
    pinMode(Led,OUTPUT);
    if (DEBUG) {
        Serial.println("Debugging Enabled");
    }
     
}
//==============================================================================
 
//=====[ LOOP ]=================================================================
void loop() {
 
    SerialParser();
         if (ByteCount  > 0) {
          Serial.print("Command     : ");
          Serial.println(Command);
          Serial.print("Data        : ");
          Serial.println(Data);
         } 
       
}

Being creative in electronics as a hobbyist

I am not an Electronics Engineer. I am not officially trained and have no related certifications. I am however, what I would call “experienced”. I was introduced to electronics as a hobby in the late 1960’s as a kid in home where electronics was paying the bills, so to speak. My father was, at the time, an electronics systems technician working for a large military contractor.

It probably started the day I “went to work” with him and he showed me the project he was working on… It was a missile launch system loaded with cool control panels and of course, Nixie number indicator tubes.

So, at around age 13 or 14, I wanted to know how all this stuff worked. Unlike today, we had nothing like the Internet so find out how stuff worked involved going to the library and reading books or the magazines of day like Popular Electronics. My dad also had a collection of technical books and schematics that I would read over and over again.

So it started to become clear to me that a “designer” would use a collection of parts and arrange them in a particular way to take advantage of their physical “laws” to achieve a particular result. It also became clear that the characteristics of each individual part were as important as how they were assembled together. A particular device is chosen based on the effect it’s value and parameters have on the overall assembly. It sometimes became clear to me that some parts are chosen based on availability and commonality making them what the assembly is built around.

In my case, I started to understand schematics and the meaning of the symbols rather quickly. I also discovered that unless I truly know what a part does, I don’t try to design with it. This lead to the start of a collection of component “data books”. Logically, these are no longer produced as it requires dead trees and we are much better served by online PDF files known as “Data Sheets”.

So, what does it mean to be a hobbyist?

Well, we are actually able to willfully misuse parts in ways they were never intended to be used, which is a luxury a professional designer doesn’t have. We don’t have a boss looking over our shoulder saying “Is it done yet? We are on a schedule here!”. In short, we can play. We can be creative. We can build and not be driven by time constraints and production budgets. We can have fun.

Where to start?

1) Try to learn some electronics theory. Nothing too deep. You should not have to go far beyond learning OHMS Law to be good enough. Lot of web resources exist already
2) Sketch your ideas out on paper before starting on the breadboard.
3) A solder-less breadboard and some jumper wires
4) Datasheets are king. Don’t try to use a part, especially a transistor or integrated circuit without one
5) Get some tools. You can get a good “temperature controlled” solder station for as little as $14. Wire cutters, needle-nose pliers and solder-sucker are all also high on the list of “should have’s”. A cheap un-controlled “fire-stick” or a “gun” type soldering iron are unsuitable for electronics.

With that out of the way… what’s next?

Find what interests you. For example, even after 50 years, we still use discrete transistors. It is still a major building block in electronics. Learning how they work can be a fun adventure so I’ll tell you about how I learned about transistors. I found a book in the library about transistor “multi-vibrators” and not having a clue what a multi-vibrator was, I started reading it. It turns out, it’s a circuit family based on a design using at least 2 transistors with a feedback path where the state of one transistor affects the state of another. Such a nice place to start. I learned about R/C (resistor/capacitor) interaction and how it could create a time delay and how this R/C behavior could create an oscillator or a circuit that could extend a small pulse into a long one.

Thus began my long journey of learning something new nearly every day… and the start of a fun hobby.

Yes, I can make a .65 Pitch breakout

Last week-end I wanted to prototype with an INA219, but I only bought the SMD version for my final design. I still wanted to play with it a bit, so I needed to mount on one a Solderless compatible format. I just didn’t have a pre-made one handy. So I made one.

Screenshot
Quick Sprint Layout Drawing


Layout File

2014-03-22_13-34-51_315_zps958360ea

2014-03-22_13-05-50_190_zps8cbc8dad

2014-03-22_14-21-17_177_zps82a3a6f6

1-wire Power Injector

One way that I get reliable 1-wire communication is to use a power injector. This means that the along with the 1-wire signals, I inject a supply voltage into additional cable pairs.  Since  the most readily available commodity cable currently is 8 conductor Cat-5 cable, chances are that you also use this cable for 1-wire cabling and have spare wires going unused. Dallas called the 1-wire bus a MicroLAN, so I will continue to use their terminology here.

For short runs, where the total length of the MicroLAN is < 30 meters and the network only has maybe 6 to 10 slave devices on it, cable selection for use on the MicroLAN is reasonably simple, as even flat modular phone cable can work with a small numbers of 1-Wire slave devices. However, the longer the MicroLAN, the more important cable properties and therefore cable selection becomes more critical.  However, since I’m dealing with 30M or less, I’ll focus on that here and leave the research for  better cable techniques for when I run into a problem.

One of the remaining issues with using 1-wire driven from an Arduino pin directly is the fact that it is also providing power to all of the devices on the the 1-wire LAN when in parasitic mode.   While 1 or 2 devices are of little concern, I started to worry about building a reliable 24/7 full time  MicroLan configuration that would report weather data from 8 or so sensors, most of which were located at the garden bed outdoors.  It became clear that some of my devices were really not performing as desired  when “parasitically”  powered when I finally put all the pieces together.

Experimentation showed me that the signal from the Arduino pin was just not up to that task of powering and communicating with all the devices without some random miscommunication here and there.  I would get values like 185F and not the 70F I was expecting from a 1-wire temperature sensor, for example.

My solution was reasonably simple.  I would create an external “middle-man” device that would insert power into the CAT-5 cable after leaving the Arduino board.  Its really just a dual supply from typical commodity wal-wart power source.  The unmodified 12VDC supply will be fed into the cable on a spare pair and treated as “unregulated” and a 5V regulator will be added to another spare pair and considered to be “regulated”.  All code will now be written to comply with the “non-parasitic” mode of 1-wire.

The Design:
1wire-power-injector

The PCB:
PI

LC Meter – Working…

This is a variation of many many other LC meters already published. It owes much of it’s design to the AADE LC meter that relies on the oscillation of a standard Analog Comparator using a capacitor and a coil. This solution is an attempt to take Kerry Wong’s Arduino implementation and simplify it a bit and to make use of latching relay for mode selection.

Notes: Initially I used a 2% tolerance .001uF capacitor and a small 5% tolerance RFC 220uH coil. results were OK, but not real close to actual values even after some tweaks so I looked for an alternative in my junk box.

I found a 1800pF Mica capacitor with 1% tolerance and a 82uH radial choke coil (Basically, the kind used in higher current situations). I did some quick math and determined that frequency of oscillation would increase to somewhere between 414473 HZ and 419973 HZ with the former being the mathematical ideal. (which I modded to an even 420000 for simplicity.)

My changes (completed and planned) to the Kerry Wong’s solution includes:

1) Software controlled backlight – no switch – I just turn it on… that works for now
2) Implementation of Latching Relay to eliminate a DPDT manual switch
3) Using an 8×2 LCD for smaller footprint
4) Battery Voltage sensing. If battery is low, shut off the backlight.
5) Push-on/push off power control with timer based auto shutoff. (5 minutes)

Testing showed me that I really didn’t like using the KHM Library from Martin Nawrath. I mean, it basically worked and that is what Kerry Wong used… but, I found that it was impacting my mode switch and calibrate button sensing. And that was just not good now that I was using a latching relay instead of a DPDT switch for mode change.

In the end, I opted for the Frequency counting library from PJRC instead:

CODE

Sprint Layout File:
Sprint Layout (V6)

Schematic:
MyPCB-LC-Chematic

Layout (only 2 minor errors crept in during etching):
MyPCB-ASBuilt

Etched PCB (tinned and sealed with matte clear laquer AKA Dullcote):
2013-05-04_21-37-03_810_zps5de5a16b

Silkscreen: Toner Transfer to TOP SIDE PCB, sealed with Future floor wax (clear acrylic)
2013-05-04_21-36-33_802_zps7ff47096

Front Panel:
panel2

LC Meter revisited

So I really liked this LC meter that Kerry Wong came up with… with the understanding that it was based on a plethora of comparator based ocillator LC meters on the web but I wanted both less and more.

Kerry Wong LCF Meter

I wanted less of the Frequency meter… I already have ways to measure frequency… and I wanted to eliminate the DPDT L/C switch.

Here is my version of the circuit:
LC_METER

You probably already knew this but… latching relays are neat

So, I’m hanging out in IRC and a guy wants to be able to use a latching relay (and hasn’t bought one yet) and wants to know how it can help his battery operated Arduino device switch contacts but not lose power to an engaged relay coil. “Simple”, I say, and then realize that I had intended on researching small current latching relays for my own project.

So here’s the circuit.

latchrelay
…and here’s the explanation.

The relay that was chosen is from the very likable OMRON G6 series of tiny relays. It is a dual coil type that latches to a position after a brief “impulse”. In this case… after the Arduino briefly supplies a connection to GND for the coil using an NPN transistor.

The specifics of the part are: G6SK-2-DC5 (You can check out the the full specs HERE )

This device is a 5V unit with a pair of 125 Ohm relay coils. (works out to be about 40 mA, too much for a MCU pin… so NPN drivers are required, not optional)

So, why do we have a DPDT unit? Because we need a spare pair of contacts to let the Arduino know which state the relay is in after power up… since it can be in either position when power off. The Arduino can know the relay’s current state by checking to see if (pin 7 in this case) a high is seen on the sense pin. The sense pin is set to draw 0.5 mA when in the SET state and 0 mA in the RESET state.

For the curious: Mouser.com stocks this part

PD2435 and Arduino using I2C Port Expander

This information has been collecting dust on my hard drive.   Time to resurrect it…  Recently I have been working on a Temperature and  Humidity display and while working on it,  decided to use these RETRO parts I got from BGMICRO sometime around 2000. Even then, these parts were considered “pure unobtanium”.  I still had a few leftover displays, so out from the parts collection they come.

Now I had never taken the time to really get these displays working on an Arduino and what I really wanted was a test that would show off how much information you can really show using only 4 characters.

Since this project was to be inserted into an already working sketch, I made sure it was as modular as possible, sprinkled with subroutines that could be called from “who knows where” to get the job done.

I’ve tried to comment where it made sense and I have drawn up a quick schematic drawing to show just how its connected.  Since this part was designed for a CPU Bus Architecture of the 70’s and 80’s, it is annoying to see how demanding it is of the limited pin resources on the Arduino. The display assumes you provide data in a Parallel 8-bit format.  To relax this demand for pins, I employed a PCF8574 ( I2C port expander) that was harvested from some abandoned electronic board.  “YAY for recycling!”

The parts I’m talking about are the PD243x displays from OSRAM.

So, what we have here is some sample code, for the Arduino, that allows you to send ASCII strings (including text scrolling) to these vintage displays.  Some of the information that helped me get beyond the datasheet was gathered from around the Internet (including blogs in New York, Japan and Korea)  Kudo’s to TechBlog in Korea for creating such a great resource.

display

Interesting side story: WAY BACK WHEN… BG Micro had horrible 3rd party photocopies of a facsimile for these parts. They were almost entirely unreadable.  At the time, datasheets were generally unavailable on the Internet,  so, after spending hours searching with “Altavista”, I finally found a clean PDF copy of the datasheet. Rather than just keep them to myself, I decided to give a nice clean datasheet back to BG Micro so they could share it with other customers who purchased the parts.

PD2435 PD24xx

DATASHEET

APPNOTE

CODE-DOWNLOAD

SCHEMATIC

CODE

//==============================================================================
// PPPP  DDDD  2222  4  4  3333  77777        III  N   N OOOOO
// P   P D   D     2 4  4      3    7          I   NN  N O   O
// PPPP  D   D  222  44444  333    7           I   N N N O   O
// P     D   D 2        4      3  7     ..     I   N  NN O   O
// P     DDDD  22222    4  3333  7      ..    III  N   N OOOOO
//==============================================================================

//==============================================================================
// Program:      PD2437.ino
// Author:       Pete Willard
// Version:      0.01
// Target:       328p IDE 1.03
// Date:         2013/01/27
// Time:         12:00:18
// Notes:

// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.

// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.

// You should have received a copy of the GNU General Public License
// along with this program.  If not, see <http://www.gnu.org/licenses/>.

// Reference: "nautes Tech Blog", "David Croft @ davidc.net"
//==============================================================================

//=====[ INCLUDE ]==============================================================
#include stdlib.h
#include Wire.h
//=====[ CONSTANTS ]============================================================
#define   DEBUG     1   // 0 = debugging disabled, 1 = enabled
// Address of PCF8574 IC on TWI bus is address 0100xxx (0x20)
// while the PCF857A address is 0111xxx. (0x38)
#define IO_ADDR (0x20)

//=====[ PINS ]=================================================================
int Led = 13;  // Not used
// Connected to PD2437 directly
int PA0 = 2;   // Address 0 (pin 9)
int PA1 = 3;   // Address 1 (pin 8)
int PA2 = 4;   // Address 2 (pin 7)
//
int WR = 7;   // Write (pin 7)
int CE = 5;   // Chip Enable (pin 6)
int RST = 6;  // Reset (NEG, pin 11)
//=====[ VARIABLES ]============================================================
char messagebuffer[21];

//=====[ SETUP ]================================================================
void setup()                    // run once, when the sketch starts
{
	Serial.begin(9600);
	Wire.begin();        // initialize the I2C/TWI interface

	// Setup pins for PD2437
	pinMode(PA0, OUTPUT);
	pinMode(PA1, OUTPUT);
	pinMode(PA2, OUTPUT);
	pinMode(WR, OUTPUT);
	pinMode(CE, OUTPUT);
	pinMode(RST, OUTPUT);

	// Reset PD2437
	digitalWrite(CE, HIGH);
	digitalWrite(WR, HIGH);
	digitalWrite(RST, LOW);
	digitalWrite(RST,HIGH);
	AsciiMode();
}
//==============================================================================

//=====[ LOOP ]=================================================================
void loop()                     // run over and over again
{

	// Can do this...
	char messagebuffer[] = "  Temperature: 68F  ";
	ClearDisplay();
	ScrollDisplay(messagebuffer);
	delay(1000);

	// Random Length String with INT value added
	int n = 34;
	sprintf(messagebuffer,"   Humidity: %2d%%  ",n);
	ClearDisplay();
	ScrollDisplay(messagebuffer);
	delay(1000);

}

//==============================================================================
//=====[ SUBROUTINES ]==========================================================
//==============================================================================

void CommandMode(){
	digitalWrite(PA2, LOW);  // enable command mode
}
//==============================================================================

void AsciiMode(){
	digitalWrite(PA2, HIGH);  // enable ASCII mode
}
//==============================================================================

void TogglePin(char bitpin) {
	digitalWrite(bitpin,!digitalRead(bitpin));
}
//==============================================================================

void PulsePin(char bitpin) {
	TogglePin(bitpin);
	TogglePin(bitpin);
}
//==============================================================================

void ClearDisplay() {
	CommandMode();
	PutChar(0, 0x83);
	delay(100);
	AsciiMode();

}

//==============================================================================
// Note: This looks funny because it reads the buffer from right to left
// Blame the display...  :-P

void WriteDisplay(char *input) {
	for (int i=0; i<4; i++) {
		PutChar(i, input[3-i]);
	}
	input = "";
}
//==============================================================================

void SetByte(int ch) {
	// Use TWI output Mode to Write to DATA BUS PINS on PD243x
	Wire.beginTransmission(IO_ADDR);
	Wire.write(ch);
	Wire.endTransmission();
}
//==============================================================================
// set address for PD243x

void SetAddr(int adr) {
	digitalWrite(PA0, (adr&0x1));
	digitalWrite(PA1, (adr&0x2));
}
//==============================================================================
// Main Character writing routine

void PutChar(int pos, int ch) {
	SetByte(ch);			// Pre-set the 8 bit data bus
	SetAddr(pos);			// pre-set the address bus
	digitalWrite(CE, LOW);	// Enable Display
	PulsePin(WR);  			// Read inputs and display it
	digitalWrite(CE, HIGH);	// Disable Diplay
}
//==============================================================================

void ScrollDisplay(char *ascii) {
	char buffer[4];
	int i = 0;
	boolean blank;
	while(ascii[i] != 0){
		blank = false;
		for (int ii = 0; ii<4; ii++) {
			if ( !blank && ascii[i + ii] == 0 ) {
				blank = true;
			}

			if ( blank ) {
				buffer[ii] = ' ';
			}
			else {
				buffer[ii] = ascii[i + ii];
			}
		}
		buffer[5]=0;
		WriteDisplay(buffer);
		delay(250);
		i++;
	}
}

No updates? I blame writers block…

Yeah, that’s the ticket.

So where am I as I start 2013.  Well, My Arduino based weather thingy is basically working.  The rain counter still dead… the now obsolete Maxim DS2423 seems a bad design choice now.  There must be a better way to keep track of the tipping rain bucket ( 5o tips per inch) that is non-volatile for those power outage times.

My Arduino based “make your own work bench tool” project is sort of stalled. Though I did find a neat oversize retro cabinet to put it in. (So 1980’s)

I’ll close up this update by sharing an old project… the Live For Speed Outgauge Bus Arduino interface (gear and RPM meter).

PC Network UDP to Serial conversion:  “PC CODE” and the Schematic.

Arduino Code: (pre-IDE 1.0)

 //----[ OutGaugeBus ]------------------------------------------------------
 // Name : OGBUS.PDE
 //-------------------------------------------------------------------------
 // Purpose : Receive serial commmands from "Live For Speed" INSIM OUTGAUGE
 // : Client and then display real-time dashboard information
 // : on Arduino based output devices, such as LED's.
 // : Live For Speed References:
 // : LFS/DOCS/INSIM.TXT
 // : http://en.lfsmanual.net/wiki/InSim_Tutorials
 // : http://www.brunsware.de/insim/
 // : See Also: http://www.lfs.net/
 //-------------------------------------------------------------------------
 // Date : 25 Oct, 2007 ( Started as a Parallax SX28 project )
 // Version : 2.11
 // Modified: 12/22/2010 11:30:34 AM
 // Author : Pete Willard
 // :
 //Additional:
 // Credits : * Mike McRoberts - Earthshine Design -
 // : Arduino Starter Kit PDF
 // :
 // : * Hacktronics - http://www.hacktronics.com/Tutorials
 // :
 // : * Arduino ShiftOut tutorial
 // :
 // : To keep code "recognizable", available references were used
 // : and changed very little from reference sources listed above.
 //-------------------------------------------------------------------------
 // Notes : Includes using a 74HC595 Shift Register for the Bar Graph
 // : and discrete 7-segment display for gear indicator
 // :
 // : Commands come from OGBUS.EXE (DevC++ UDP Client) and convert
 // : INSIM OUTGAUGE data into serial packet data for Arduino
 // : INSIM Client Software will send ALL vaalues every update
 // : but can send as little as Clear Command "C0"
 // :
 // : Expansion:
 // : With a little creative wiring, it would be possible to
 // : daisy chain multiple serial Arduino boards or if USB is
 // : used, multiple OGBUS clients can be run at one time
 // :
 // : Command Examples:
 // : (Comma Separated Values) Any Order up to 24 Characters
 // : Format: <command></command>,<command></command>...
 // : C0 = Clear All Outputs
 // : G0-G8 = Gear Indicator
 // : R0-R8 = RPM Bargraph
 // : S0|S1 = Shift Light Pin On|Off (binary)
 // : P0|P1 = Pit Limiter Pin On|Off (binary)
 // :
 //-------------------------------------------------------------------------

//----[ Variables ]--------------------------------------------------------
 const int buffsize = 25; // Buffer Size
 char buffer[buffsize]; // Incoming Serial Data Buffer
 int debug = 0; // Set to NON-ZERO to test with Serial Monitor
 int ledCount = 8; // The number of LEDs in the Bar Graph LED
 //-------------------------------------------------------------------------
 // Seven segment LED layout for the Gear Indicator
 // Arduino pins must be sequential
 int GIstartpin = 2;
 // Arduino pin: 2,3,4,5,6,7,8
 byte seven_seg_digits[9][7] = { { 0,0,0,0,1,0,1 }, // = R
 { 0,0,1,0,1,0,1 }, // = N
 { 0,1,1,0,0,0,0 }, // = 1
 { 1,1,0,1,1,0,1 }, // = 2
 { 1,1,1,1,0,0,1 }, // = 3
 { 0,1,1,0,0,1,1 }, // = 4
 { 1,0,1,1,0,1,1 }, // = 5
 { 1,0,1,1,1,1,1 }, // = 6
 { 0,0,0,0,0,0,0 }, // = 7 (blank)
 };
 // a b c d e f g ------> LED segment
 //-------------------------------------------------------------------------
 // Bargraph Values for 8 LED Bargraph
 // Only 8 values of BYTE are needed to light the 8 bargraph LED's
 // sequentially
 // NOTE: Most Bargraph LED's are "10 unit" so I have bottom 2 and top 2
 // LED's tied together.
 // Part Number used: AVAGO "HDSP-4832" 3-Green 4-Yellow 3-Red
 // Mouser Part Number: 630-HDSP-4832
 // The Shift Register lowest outputs start with Green Anodes of the
 // Bargraph.
 //
 byte bargraph[9] = {0x00,0x01,0x03,0x07,0x0F,0x1F,0x3F,0x7F,0xFF};
 //-------------------------------------------------------------------------
 // LED PINS - optional since we are low on pins
 int shiftlight = 12;
 //int pitlimit = 13; // Pick one
 //int lowfuel = 13;
 //-------------------------------------------------------------------------
 // 74HC595 Pin Setup
 int latchPin = 9; // Pin connected to ST_CP (12) of 74HC595
 int clockPin = 10; // Pin connected to SH_CP (11) of 74HC595
 int dataPin = 11; // Pin connected to DS (14) of 74HC595

//----[ SETUP ]-----------------------------------------------------------
 void setup() {
 // Speed needs to match INSIM - Outgauge Client Configuration setting
 Serial.begin(19200);
 Serial.flush();

// Set all pins to Outut Mode
 int a;
 for(a=0;a < 13;a++){ pinMode(a, OUTPUT); 
 } 
} 

//----[ MAIN LOOP ]------------------------------------------------------ 
void loop()  { 
// Mike McRoberts serial input command routines 
// from the "Serial Controlled Mood Lamp" example 
// in Arduino Starter Kit Manual from Earthshine Design 
if (Serial.available() > 0) {
 int index=0;
 delay(10); // let the buffer fill up
 int numChar = Serial.available();
 if (numChar>buffsize) {
 numChar=buffsize;
 }
 while (numChar--) {
 buffer[index++] = Serial.read();
 }
 splitString(buffer); // Process Serial Packet
 }
 }

//----[ SubRoutines ]----------------------------------------------------

void splitString(char* data) {
 // also from "Serial Controlled Mood Lamp" example

if (debug) {
 Serial.print("Data entered: ");
 Serial.println(data);
 }

// Sequentially De-Tokenize the Serial Commands received
 char* parameter;
 parameter = strtok (data, " ,");
 while (parameter != NULL) {
 // Pass result to parseCMD for each Command received
 parseCMD(parameter);
 // remove processed commands from the list
 parameter = strtok (NULL, " ,");
 }

// Clear the text and serial buffers
 for (int x=0; x<buffsize; x++) {
 buffer[x]='\0';
 }
 Serial.flush();
 }

//=======================================================================
 void parseCMD(char* data) {
 // Flexible, easily expanded Command Parser
 // based on "Serial Controlled Mood Lamp" example
 // *** Marvelous coding by Mike MCRoberts

//--[gear]---------------------------------------
 if ((data[0] == 'G') || (data[0] == 'g')) {
 // Have command, now get Argument "value" while removing whitespace
 int ArgVal = strtol(data+1, NULL, 10);
 // then limit the results to what we expect for this command
 ArgVal = constrain(ArgVal,0,8);
 sevenSegWrite(ArgVal);

if (debug) {
 Serial.print("Gear is set to: ");
 Serial.println(ArgVal);
 }
 }

//--[shift light]--------------------------------
 if ((data[0] == 'S') || (data[0] == 's')) {
 int ArgVal = strtol(data+1, NULL, 10);
 ArgVal = constrain(ArgVal,0,1);
 digitalWrite(shiftlight,ArgVal);

if (debug) {
 Serial.print("SHIFT is set to: ");
 Serial.println(ArgVal);
 }
 }

//--[reset]--------------------------------------
 if ((data[0] == 'C') || (data[0] == 'c')) {
 int ArgVal = strtol(data+1, NULL, 10);
 ArgVal = constrain(ArgVal,0,1);

sevenSegWrite(8);
 shiftWrite(0x00);

if (debug) {
 Serial.print("Clear Outputs");
 }
 }

//--[rpm bar graph]-----------------------------
 if ((data[0] == 'R') || (data[0] == 'r')) {
 int ArgVal = strtol(data+1, NULL, 10);
 ArgVal = constrain(ArgVal,0,8);

shiftWrite(bargraph[ArgVal]);

if (debug) {
 Serial.print("RPM is set to: ");
 Serial.println(ArgVal);
 }
 }

} // End parseCMD Loop

//=======================================================================
 void sevenSegWrite(byte digit) {
 byte pin = GIstartpin;
 for (byte segCount = 0; segCount < 7; ++segCount) {
 digitalWrite(pin, seven_seg_digits[digit][segCount]);
 ++pin;
 }
 }
 //=======================================================================
 void shiftWrite(byte Rdata){
 // prepare the register for data
 digitalWrite(latchPin, LOW);
 // shift out the bits:
 shiftOut(dataPin, clockPin, MSBFIRST, Rdata);
 //Set the latch pin high to enable the outputs
 digitalWrite(latchPin, HIGH);
 }