I2C 4-Digit LED Interface

In an earlier project I detailed an I2C (two-wire) interface to the common 1602 LCD.  Recently I found a cheap 4-digit LED module that uses a pseudo I2C interface.  I don’t have a particular need for it but I went ahead and added one to a parts order I made.  If you know a little about I2C you know that it is a serial interface where the controlling circuit provides the clock and controls the direction of the single data line.  Usually you can hang several I2C modules on the same pair of line (e.g.: clock module and display module) because each module has a unique address.  I said this LED module has a “pseudo I2C” interface because it does not have an address.  That means that it needs to be the only device using the data line.

LED I2C Module

TM1637 Module

The module I have is similar to the one shown here.  It is typically listed as part number TM1637.  You can find a variety of information on the web but I had a hard time finding all of the details I needed.  I also looked at some existing code (Python and C) which can often be a dangerous thing to do.  The one critical thing I determined from the code was that the data bits sent to the LED module need to be LSB first.  That differed from the approach for the other I2C projects I have done.  Another idiosyncrasy that I noted is that the addresses for the digits go from left to right (starting with address C0).  That means that data must be written from most significant digit to least significant digit if using the auto increment addressing mode.  In fixed addressing mode you would just pick the appropriate digit and write directly to it.

I2C Communications

I2C communications are accomplished by using just two wires: one for data (SDA) and one for a clock (SCL).  The data line is defined as being bidirectional so there needs to be a “master” device on the bus to control things.  The clock rate is limited by the slowest device on the bus and controlled by the master device.  Basically it sets a data bit and then toggles the clock line.  At the end of each byte transfer the master reverses the direction of the data line and then clocks in the acknowledgement bit from the slave device.

There are three basic commands for the LED module.  One controls the on/off and brightness of the display, one controls the address of the digit to write, and one controls the addressing mode (fixed or auto increment).  Usually an application will just load all four digits each time so the auto increment mode is normally used and the address set to the first (left-most) digit.


LED I2C Interface

The connections to the PIC are pretty simple with only two I/O pins being used.  That leaves four other pins on our little 12F683 for getting sensor data.  This same connection can be used with the 16F688 if we want more I/O pins.  The module already has the required pull up resistors on the SDA and SCL lines.


The software link is listed below.  While it is targeted for the 12F683, it is easily ported to bigger versions of the PIC like the pin compatible 16F688 that I use for a lot of my projects.  Some of the newer PICs also have a hardware I2C interface so most of the related software routines would be greatly reduced or eliminated.

The I2C routines are the same as those I wrote for the LCD project but a lot of the other LCD-specific code was not needed for the LED module.  I added a lookup table that converts single packed ASCII characters to the required LED segments.  I also added a second test routine that shows how you can make non-ASCII displays by turning on the right segments.  The data bit associations for the segments are shown in the header of the software source code.  The eighth bit in the segment bytes is reserved for turning on the colon that resides between digits 2 and 3 on the module.  In my tests it appeared that all four characters had to include a 1 in the eighth bit in order for the colon to light.

I added a line of code to the end of the “i2cwaitack”routine to try and recover if the slave does not acknowledge the data transfer.  If the slave fails to acknowledge a transfer then the software will be reset by enabling the Watch Dog Timer (WDT).  Newer PIC chips have a software reset command that can be used instead.  An alternative for some I2C applications would be to simply make a call to “i2cstop” and then continue where the code left off.  That’s it for this post.  Check out my other electronics projects at boomerrules.com.


Intruder Alert

In an earlier post on my website I detailed a PIC microcontroller project that allowed me to capture information about a variety of RF security system sensors I have.  In this post I have taken the information I collected for a cheap 433-MHz motion detector I bought on ebay and turned it into a usable circuit.  In addition to the PIC, I use an RF receiver module and a solid state voice recorder/player.  All of the parts, including the motion detector, cost less than $15 total so you can have some cheap fun with this project.



The motion detector module I used looks like the picture above.  It uses a 12 volt battery and has an extendable whip antenna.  The RF signal it puts out is strong enough that I didn’t even have to add an antenna to my RF receiver board for use in my house.  I used a sensor logger circuit (detailed in another project on my website) to determine the sync and bit times for the sensor as well as the actual data bytes.  The sensor outputs 24 bits (3 bytes) of data and each sensor has a different pattern.  There is also one stop bit.  The sync time turned out to be 10ms and the bit times were about 320us and 970us.  I verified this with a second sensor and also by capturing the RF receiver output on my oscilloscope.  There are many examples online that detail how to capture this information using a PC audio card.

RXB6 Front

The RF receiver module I prefer is a super heterodyne receiver called the RXB6.  It has much better range than the cheaper receivers that commonly get paired with an RF transmitter module.  In fact, when I was trying to buy a few extra RF transmitters I ended up buying them with the cheap receivers for less than 60 cents a set from a USA seller.  I’ve kept the bad receivers for now but will likely never use them.

ISD1820 Module

The sound recorder/player module is commonly listed as ISD1820.  That’s actually the chip part number but it’s also the module designation.  The particular version I bought is shown in the picture but pretty much all of them work the same.  It’s convenient to have the push buttons on the module so you can do the recording and verify the playback before embedding it into your circuit.  These modules are typically set up for a maximum of 10 seconds of recording but the manual shows how to modify them for shorter or longer times.  The maximum time is 20 seconds but the tradeoff is lower quality.  It’s probably not a problem for simple voice messages.  I was pleasantly surprised at the clarity of the recording.

Motion Detector

The schematic is shown above.  The sound modules are often advertised as being able to run on 5 volts but the recommended range for the chip is 2.7-4.5 volts.  Just to be safe I’ve added a cheap 3.3 volt regulator (LM1117) to drive the sound module.  That also means that the play trigger from the PIC needs to be reduced in voltage so a simple resistor voltage divider is used.  The resistor values are not critical.  Just try to get the ratio of values to about 2:3.


There are some defines in the first part of the software that may need adjustment for your application.  There are defines for the sync time (in milliseconds) and the 0/1 bit times.  The bit times are actually for the OFF part of each bit because that is how the software does the measurement.  The bit times are not in milliseconds but are the expected count for the upper half of Timer1.  Each count in TMR1H represents 128 microseconds based on the 8-MHz clock frequency of the PIC.  This simplification works because the shorter bit time will always exceed 256 microseconds but never exceed 384 microseconds.  Likewise, the longer bit time will always exceed 896 microseconds but never exceed 1024 microseconds.  Again, this is based on measurements I made for my sensors.  Yours may be different.  Another set of defines is included to represent the byte values transmitted by the sensor.  These will be different for your sensor.

The software uses the 16-bit Timer1 to measure the sensor bit durations by counting only during the low level part of each bit.  That meant that I needed to use the T1G (Timer1 Gate) input of the PIC.  I also wanted to check on the pulse counts when they completed so I used the INT (external interrupt) input and set it to trigger on a rising edge.  Each bit (including the stop bit) always starts with a rising edge.  The bit value (0/1) is determined by the duration of the high part of each bit but we actually measure the low part because we also want to measure the low level time between data messages for the sync.

The interrupt handler is triggered by the rising edge of each bit.  At that point the upper half of Timer1 is read.  If the Synced flag is not yet set, then the software determines if we have measured a sync pulse.  The math is easy because all we do is round up (add 4) and then right shift three times (divide by 8).  That gives us the integer number of milliseconds.  If the value matches our required sync time then the Synced flag gets set.  That allows us to skip directly to the bit measurement part of the code for subsequent interrupts.  If a bit time matches, then it is packed into RF_Byte and the Bit_Found flag gets set.  If a bit time doesn’t match then everything previously collected is discarded and we wait for a new sync pulse.

After the return from an interrupt, the main part of the software checks the Bit_Found flag to determine if it needs to take action.  If a complete byte has been received then the software checks the value against the expected value for the sensor.  That is done by calling a simple lookup table with the indices for the table being the variable Byte_Count.  If a byte doesn’t match, then everything is discarded and we wait for a new sync pulse.  If all three bytes have been received and match, then the software sends a high-level pulse to trigger the sound module.  An Alarm LED is also turned on and remains on until power is cycled.  The reason I added that is to facilitate testing and as an event memory.  That way I can position the sensor and receiver at different locations and verify successful operation without having to use a second person to listen for the sound.  I can also test sensor locations to make sure that heater/cooler air flow or one of our cats doesn’t cause a false trigger.  That’s it for this project.  be sure to check out my other projects on my website: boomerrules.com

Motion Detector

Rootin’, Tootin’, Shootin’ Game

When I lived in Orange County, California two of the biggest employers of college kids were Disneyland and Knott’s Berry Farm.  Because I had electronics training from the military I was able to get a job in the Knott’s shooting gallery instead of having to wear a funny costume.  The rifles used high voltage flash tubes with focusing lenses and the targets used photo cells.  The target counter circuits used germanium transistors set up as flip-flops.  The transistors were becoming harder to find so someone had tried replacing them with silicon ones.  Unfortunately, they found out that the fast switching times of the silicon transistors made them much more susceptible to noise.  That meant that a single hit on the target would ripple through the counters and light all of the lamps at once.  The lesson here is that sometimes slow is good.

Recently I was thinking about those days and decided to see if I could design a simple shooting game for my grandkids.  The game detailed here pits two players against each other to see who can get to five hits first.  I also decided to use a cheap red laser diode as the heart of the gun.  You could use laser pointers if you want but the circuit I include for the gun ensures that you get a single shot instead of a steady on beam.

Light Sensor Modules

Light Sensor Module

At first I was going to just use photo transistors for the sensor circuits but then I discovered the light sensor modules shown above.  I bought a pack of 10 for next to nothing from a China supplier.  The modules do use a photo transistor but they run the sensor voltage into an LM393 comparator so it provides a digital output as well as an analog one.  A potentiometer onboard can be adjusted to set the trip level of the comparator.  It also includes a power on LED and an LED that lights when the comparator switches the digital output.  That makes it easier to adjust the proper level.

Target Hardware


The bulk of the hardware consists of 10 LEDs and 10 resistors.  I used standard 5mm bright white LEDs for indicators 1-4 and a slow flashing LED for the 5th indicator.  The switch is normally open momentary contact and is used to reset the game.  The PIC microcontroller is a standard one that I’ve used in other projects.  As you can see in the pictures, I built the LED modules separately in order to make it easier to locate them in a target.

Target Layout

Target Top

Gun Hardware

Laser Gun

The basic hardware and schematic for the laser gun is shown above.  I built mine into plastic toy airsoft guns.  The barrel tube for the pellets is almost the perfect size for the laser diode modules and I was able to fit a battery holder for two AAA batteries in the opening for the magazine.  There are plenty of cheap laser diode modules out there and basically they differ only in the value of the current limiting resistor mounted onboard.  That resistor determines the voltage rating of the laser module.  I use two AAA batteries so I picked 3 volt lasers.  The switch is a single pole, double throw micro switch.  The capacitor is used to force a single burst of light with every pull of the trigger.  In one position of the switch the capacitor charges up and in the other position it discharges through the laser.


Like all of my PIC projects, the software is written in assembly language.  What makes this project a bit unusual is that the Main routine does nothing because all of the action takes place in the interrupt handler.  The PIC has a feature called interrupt-on-change which, in older PICs, generates interrupts on any positive to negative or negative to positive transition on an I/O pin.  This particular PIC allows the software to set the interrupt source to be either the positive edge, negative edge, or both edges.  The light sensor module will generate both edges on a transition so this feature is quite handy.  In this case, the software waits until the sensor output switches back high (off) before the interrupt is generated.

When a sensor interrupt is received, the software temporarily disables that input and sets a timer.  In effect, the timer acts like a debounce circuit for a switch.  At the 8-MHz clock selected for the PIC and the setup for the timer, the total timeout is about 130ms.  When the timer finishes, it also generates an interrupt.  At that point, the sensor input is re-enabled.  Each sensor input has its own dedicated timer so there is no conflict between players.

Each sensor interrupt will also light one of the LEDs for that player.  Instead of a counter, the software uses a variable that has one bit set.  That bit gets left shifted with each interrupt and is then OR’ed into the output port to light the next LED.  When the last LED is lit, the interrupt handler disables further interrupts and that effectively locks out the other player.  The reset switch is connected to the MCLR input of the PIC and the configuration bits are set to allow that function.  When reset is pressed, the software will reinitialize and clear the LEDs.  That’s it for this post.  Check out my other electronics projects.

Shooting Game SW