My Digidash project
Posted: Mon Nov 23, 2009 4:44 am
Hello!
One of the things I've been working on sporadically over last few years is a LED display digidash, built in the golden eighties style, but with a bit of modern technology thrown in. Here's how I wanted the thing to look:
That's 518 LED's (and that's not counting the 16-segment display I forgot in that picture) plus one 8-character parallel-input ASCII display to control... no small task! The larger gauges have 96 LED's while the smaller have 32 and ten (or sixteen if the space permits). All bar graph displays are backed by 3x7 segment displays.
The basis for the unit is simple. A PIC18F458 has the required features, and an Allegro A6832, a 32-bit latching shift register, able to source 125mA, will be used as a display driver; it's actually a thermal printer head driver. I'll introduce the CPU now, and other bits later.
First, the input conditioning:
(click for a bigger picture)
Active low inputs
First, there's grounding inputs for various warning lights on the dash, such as low oil or low fuel. The odd number-letter combination derives from Mazda connector code; I've made this to fit my own car(s) so using those codes help keeping things in order. The inputs are protected with diodes to prevent possible battery voltage from entering the circuit. The output signals are the moved forward in semi-intelligible lines, like Fuel for "No Fuel". 10k pull-up resistors limit the current on these.
Active high inputs
The signals for indicators and high-beam (yep, even these are driven through the system) are active high inputs instead. On these, the 14v battery voltage is brought down to logic levels with a voltage divider. While there's no voltage, the MOSFET remains non-conductive. As soon as the input line gets voltage, the MOSFET goes conductive, and the output signal drops to zero.
Charge light
Now, this one's a bit different. In the car it's actually used to charge the field coils for the alternator, with a diode pointing into the alternator. When the battery charged the alternator, current passes through the diode and the charge light is lit. Once the alternator start producing current, the voltage bias on the diode is reversed, there's no more current and the light goes out. Now here, the current limiting is arranged by high-power 2 ohm resistor, and the bias detection is arranged with a 741 Op-amp. While the current runs through the ballast resistor, the inverting input at the battery side sees a higher voltage, and the output swings toward VSS (or just ground here). Once the alternator gets into action, the non-inverting input sees higher voltage, and the output is swung to VCC. The current running through this circuit is rather substantial, so wide traces are needed on the board.
pulse inputs
These are for vehicle speed and RPM. On the vehicle speed, a pulse sender is used; these might be available commercially or DIY'ed somewhat trivially. There is a highh-pass filter, I don't expect further problems On the engine speed side, the circuit is filtered with high-pass filter set to about 670Hz. An optocoupler is used to isolate the coil signal from the rest of the circuit.
analog inputs
A simple voltage divider is used to source a voltage signal with these. (in older cars the analog sensors were used as rheostats to limit current, and the needle actuation was by a bending a bi-metal strip that was heated with the current!). I've included inputs past the OEM specification, as I know I'll be using these. The resistor values (in my case) are 30 ohms for fuel quantity and 15 for engine temp; these give a swing of roughly 1.7 - 4 volts, which is good enough. There is no input conditioner for a lambda sensor; for that I'm running a wire straight from the connector to the analog input. Anything I would come up with would be nowhere near enough JAW or LC-1 (that I have) to warrant the effort. The RControl is for remote control which would use an external resistor network with resistors staged in 2^n values for a simple one-wire communication.
EGT
I originally planned for using a 741 and software correction, but the better solution was simpler. A MAX6675 circuit is used to interface to the CPU.
With that done, here's the actual CPU:
Power sources
The first regulator is an LM340 that's connected to continuous voltage (this might be changed into lower power unit.) This keeps the MCU and RS232 interface alive when the car is shut down. The second LM340 is used to drive logic circuits and analog voltage; it's connected to ignition voltage line, so the dash is only active when the ignition's on. Finally, the third regulator is a 5-amp LM 1084 regulator, and that's for driving LEDs. (32*125mA!) The filtering is done by regular polymer capacitors and a few big cans to compensate for voltage drops during crank. Running the input lines through a ferrite ring a few times and the Zeners should take care of spikes.
There's an interesting possibility here; using a gear-on-neutral switch input and the handbrake signal, it would be possible to make an MCU driven turbo timer function by connecting the switched and continuous power lines with a MOSFET. Just saying...
The microcontroller
The microcontroller of choice is PIC18F458. It's pretty well featured; in fact, everything except the parallel port is in use! (and even that is... in some manner) The I/O from top down is like this:
AN0, the ADC input port in use (actually I might turn these two around). Analog input is multiplexed for sixteen inputs. The latency is not an issue here really, it's more than acute enough for human input.
AN1, unused pin, routed to header
VREF- Ground reference for ADC. Probably an overkill but why not.
VREF+ VCC reference for ADC. Same as above.
T0CKL Timer 0 clock input. Used for vehicle speed clock input.
RA5 not used at this time.
OSC2 second input for external XTAL.
INT0 Speed measuring cycle completed
INT1 RPM measuring cycle completed
CANTX signal to CAN transceiver
CANRX signal from CAN transceiver
RB4 Odometer mode change and trip, also message acknowledge button if there's need for one.
PGM/PGC/PGD: ICSP pins. Routed to ICSP header.
T1CKL Timer1 clock, for RPM clock signal
RC1 routed to pin header
CCP PWM capture to detect dashboard light dimmer setting. Needed for ASCII display dimming (software driven)
SCK SPI serial clock
SDI Serial Data In (SPI bus)
SDO Serial data out (SPI bus)
DX Data sent to RS232 interface
RX Data received from RS232 interface
RD0-RD3 4-bit parallel signal sent to SPI address demuxer and analog multiplexer.
RD4 Speed clock circuit reset
RD5 RPM clock circuit reset
RE0 blanking signal for display driver
RE1 Address signal for display panels
RE2 Clear signal for display panel address memory.
VDD, VSS: as it says on the tin.
MCLR startup reset. Set to float, the MCU should power up fast enough for Power-on reset.
OSC1 external oscillator pin 1
The oscillator is 10MHz unit, the CPU is brought to 40MHz with high-speed PLL mode. This is to minimize any RFI.
Analog multiplexer
Chip used is DG406, which both TTL and CMOS compatible. For a larger number of possible analog inputs, the analog signals are all multiplexed with a 16-channel miutiplexer. The channel selection is by the same A0-A3 address signals that are used to assign the SPI devices. Because the enable pin does not require strobing, it is tied to VCC permanently.
SPI address controller
74154, a 4-bit demultiplexer is used for this task. The output is inversed, which follows the active low chip select method of SPI devices. Only three are in use for now, the rest are routed to header pins. This unit won't require strobing either, so here the both !enable -pins are tied to GND.
Parallel to serial shift registers
The caution light signals are converted into a 16-bit serial word with two 74165 8-bit shift registers. The procedure is as follows: as the SPI line "MUX1" goes low, the SPI clock signals start shifting the bits toward the output. Using inverting output, the active lows are converted into active highs; when later the registers are written into display driver, the bits are already in the right logic. After reading the information, the registers are filled with zeros because the input for MUX2 is tied to GND. If for some reason the signal input circuitry fails, it would light up the malfunctioning system. The DDRIVER SPI signal is tied to !LOAD pin; thus at every display write the data on the parallel inputs are loaded into the registers and no extra steps are needed.
canbus transceiver
MCP2551 minimum component CAN tranceiver. According to the example circuit in the datasheet, the CAN module can be used to connect the unit into a CAN bus if present. The system can have suthority on the bus, or be a listening node.
RS232 interface
The only module besides the MCU to receive uninterrupted power, the RS232 is intended for configuring the system with a PC. Circuit according to Maxim MAX232 datasheet.
Display driver
The display driver is used by SPI interface, and it has the same maximum data clock as the PIC, 10MHz. To get the number of LEDS lit up with 32 bits, the system first writes the address of the required cathode on the line, and as the flip-flops on the display end have registered the correct address, the double word for required leds are thrown in the bus. The A6832 is capable of sourcing 125mA per line, this is about the same as the forward current on non-restricted LED. There's online resistors in the bus just in case, though.
Speed and RPM clock circuitry
This circuit handles the timing of RPM and vehicle speed sensors. Instead of guessing the elapsed time with a program loop counter, this circuit will tell exactly (more or less) the period of RPM and speed signals. The crystal frequency is 32768kHz; this is the frequency used for real time clock circuits. The beauty of it is one second is exactly 2^15 cycles. The circuit for creating clock pulses from a crystal was nicked from Discover Circuits, they had a good one. The clock pulses are delivered into PIC pulse counter by an NPN transistor, which is tied to !Q output pin of a 74112 D-type Flip Flop. While the chip is in reset mode, the pin !Q is high, and the NPN is conductive. There's a 4.7M resistor to limit the base current. The pulses from the speed pickup and coil are put onto the B input pins on the 74360 decade counter. The output pin QA will create a square wave based on the pulse count; the pin is held high from 5 to 9. When the counter rolls over to zero, the output falls low. The flip-flop will detect this and trip; the pin !Q will go low, and the transistor will go non-conductive. Also the output Q will go high, and cause an interrupt on the PIC. Now the PIC will move the counter data into memory, reset the internal counter and send a reset pulse to the JK flip flop for a new batch of pulses. Since the speed difference is vast (40 MHz vs 32 kHz) the PIC should finish the task before the RTC has completed one cycle.
PIC pulse counter rollover happens after two seconds, so it's worth it to run a sanity check here. Let's say lowest reasonable engine RPM you'd expect of a car engine is 600 RPM. That's already 10Hz, and since the coil will fire twice per revolution, the decade counter will roll over every half second. For the vehicle speed, a good estimate is one revolution of the speedometer gauge per half a metre. Since the gauge can display speeds down to 1 unit per hour, it would be reasonable to expect it to do so. 1 km/h is 0.28 m/s, or a full rotation in just a bit under two seconds. For acceptable pulse rate there must be at least ten pulses per rotation.
Finally, the connectors:
The connectors between the car and the CPU are Molex Microclasp connectors, very professional and affordable too (http://www.mouser.com/catalog/629/1185.pdf), unfortunately they're rated only for 3A per pin so they're bit too weak for ECU use (I need to multiply certain pins too).
The connection to gauge panels is via 40-pole ribbon cable, essentially similar to IDE cables. The current capacity is a big issue (With all 32 LEDs powered up, the load is four amps for four lines!). If it gets into a problem, a thicker external wire will be used for LED cathode wire. At first, metallic binder clips are used for heatsinks and the gauge pod will have a chassis fan. The ribbon cable will be quite hot in any case.
The connector for CANbus is standard DE9, and the RS232 is just a header on the circuit board. The idea is the actual connector will be placed somewhere you don't need to take the car apart to access it.
All expansion pin pads are left empty, and will thusmake a sort of veroboard zone on the PCB. There are zones for free CPU pins, SPI channels (with SDI and SDO pins conveniently near by too), analog channels, parallel to serial converter pins, and case connector pins. The number of vacant addresses on the display bus at the moment is eight, so with a led bar and 3x7 display forming an unit there's room for four extra gauges.
It's 5.05AM, I'm tired as hell, but I hope that covered the basics on the CPU in an understandable way. Comments are welcome. Next update will be about the gauge panels. It's a "bit" ambitious project, but I'm hopeful I'm able to build one in the future.
One of the things I've been working on sporadically over last few years is a LED display digidash, built in the golden eighties style, but with a bit of modern technology thrown in. Here's how I wanted the thing to look:
That's 518 LED's (and that's not counting the 16-segment display I forgot in that picture) plus one 8-character parallel-input ASCII display to control... no small task! The larger gauges have 96 LED's while the smaller have 32 and ten (or sixteen if the space permits). All bar graph displays are backed by 3x7 segment displays.
The basis for the unit is simple. A PIC18F458 has the required features, and an Allegro A6832, a 32-bit latching shift register, able to source 125mA, will be used as a display driver; it's actually a thermal printer head driver. I'll introduce the CPU now, and other bits later.
First, the input conditioning:
(click for a bigger picture)
Active low inputs
First, there's grounding inputs for various warning lights on the dash, such as low oil or low fuel. The odd number-letter combination derives from Mazda connector code; I've made this to fit my own car(s) so using those codes help keeping things in order. The inputs are protected with diodes to prevent possible battery voltage from entering the circuit. The output signals are the moved forward in semi-intelligible lines, like Fuel for "No Fuel". 10k pull-up resistors limit the current on these.
Active high inputs
The signals for indicators and high-beam (yep, even these are driven through the system) are active high inputs instead. On these, the 14v battery voltage is brought down to logic levels with a voltage divider. While there's no voltage, the MOSFET remains non-conductive. As soon as the input line gets voltage, the MOSFET goes conductive, and the output signal drops to zero.
Charge light
Now, this one's a bit different. In the car it's actually used to charge the field coils for the alternator, with a diode pointing into the alternator. When the battery charged the alternator, current passes through the diode and the charge light is lit. Once the alternator start producing current, the voltage bias on the diode is reversed, there's no more current and the light goes out. Now here, the current limiting is arranged by high-power 2 ohm resistor, and the bias detection is arranged with a 741 Op-amp. While the current runs through the ballast resistor, the inverting input at the battery side sees a higher voltage, and the output swings toward VSS (or just ground here). Once the alternator gets into action, the non-inverting input sees higher voltage, and the output is swung to VCC. The current running through this circuit is rather substantial, so wide traces are needed on the board.
pulse inputs
These are for vehicle speed and RPM. On the vehicle speed, a pulse sender is used; these might be available commercially or DIY'ed somewhat trivially. There is a highh-pass filter, I don't expect further problems On the engine speed side, the circuit is filtered with high-pass filter set to about 670Hz. An optocoupler is used to isolate the coil signal from the rest of the circuit.
analog inputs
A simple voltage divider is used to source a voltage signal with these. (in older cars the analog sensors were used as rheostats to limit current, and the needle actuation was by a bending a bi-metal strip that was heated with the current!). I've included inputs past the OEM specification, as I know I'll be using these. The resistor values (in my case) are 30 ohms for fuel quantity and 15 for engine temp; these give a swing of roughly 1.7 - 4 volts, which is good enough. There is no input conditioner for a lambda sensor; for that I'm running a wire straight from the connector to the analog input. Anything I would come up with would be nowhere near enough JAW or LC-1 (that I have) to warrant the effort. The RControl is for remote control which would use an external resistor network with resistors staged in 2^n values for a simple one-wire communication.
EGT
I originally planned for using a 741 and software correction, but the better solution was simpler. A MAX6675 circuit is used to interface to the CPU.
With that done, here's the actual CPU:
Power sources
The first regulator is an LM340 that's connected to continuous voltage (this might be changed into lower power unit.) This keeps the MCU and RS232 interface alive when the car is shut down. The second LM340 is used to drive logic circuits and analog voltage; it's connected to ignition voltage line, so the dash is only active when the ignition's on. Finally, the third regulator is a 5-amp LM 1084 regulator, and that's for driving LEDs. (32*125mA!) The filtering is done by regular polymer capacitors and a few big cans to compensate for voltage drops during crank. Running the input lines through a ferrite ring a few times and the Zeners should take care of spikes.
There's an interesting possibility here; using a gear-on-neutral switch input and the handbrake signal, it would be possible to make an MCU driven turbo timer function by connecting the switched and continuous power lines with a MOSFET. Just saying...
The microcontroller
The microcontroller of choice is PIC18F458. It's pretty well featured; in fact, everything except the parallel port is in use! (and even that is... in some manner) The I/O from top down is like this:
AN0, the ADC input port in use (actually I might turn these two around). Analog input is multiplexed for sixteen inputs. The latency is not an issue here really, it's more than acute enough for human input.
AN1, unused pin, routed to header
VREF- Ground reference for ADC. Probably an overkill but why not.
VREF+ VCC reference for ADC. Same as above.
T0CKL Timer 0 clock input. Used for vehicle speed clock input.
RA5 not used at this time.
OSC2 second input for external XTAL.
INT0 Speed measuring cycle completed
INT1 RPM measuring cycle completed
CANTX signal to CAN transceiver
CANRX signal from CAN transceiver
RB4 Odometer mode change and trip, also message acknowledge button if there's need for one.
PGM/PGC/PGD: ICSP pins. Routed to ICSP header.
T1CKL Timer1 clock, for RPM clock signal
RC1 routed to pin header
CCP PWM capture to detect dashboard light dimmer setting. Needed for ASCII display dimming (software driven)
SCK SPI serial clock
SDI Serial Data In (SPI bus)
SDO Serial data out (SPI bus)
DX Data sent to RS232 interface
RX Data received from RS232 interface
RD0-RD3 4-bit parallel signal sent to SPI address demuxer and analog multiplexer.
RD4 Speed clock circuit reset
RD5 RPM clock circuit reset
RE0 blanking signal for display driver
RE1 Address signal for display panels
RE2 Clear signal for display panel address memory.
VDD, VSS: as it says on the tin.
MCLR startup reset. Set to float, the MCU should power up fast enough for Power-on reset.
OSC1 external oscillator pin 1
The oscillator is 10MHz unit, the CPU is brought to 40MHz with high-speed PLL mode. This is to minimize any RFI.
Analog multiplexer
Chip used is DG406, which both TTL and CMOS compatible. For a larger number of possible analog inputs, the analog signals are all multiplexed with a 16-channel miutiplexer. The channel selection is by the same A0-A3 address signals that are used to assign the SPI devices. Because the enable pin does not require strobing, it is tied to VCC permanently.
SPI address controller
74154, a 4-bit demultiplexer is used for this task. The output is inversed, which follows the active low chip select method of SPI devices. Only three are in use for now, the rest are routed to header pins. This unit won't require strobing either, so here the both !enable -pins are tied to GND.
Parallel to serial shift registers
The caution light signals are converted into a 16-bit serial word with two 74165 8-bit shift registers. The procedure is as follows: as the SPI line "MUX1" goes low, the SPI clock signals start shifting the bits toward the output. Using inverting output, the active lows are converted into active highs; when later the registers are written into display driver, the bits are already in the right logic. After reading the information, the registers are filled with zeros because the input for MUX2 is tied to GND. If for some reason the signal input circuitry fails, it would light up the malfunctioning system. The DDRIVER SPI signal is tied to !LOAD pin; thus at every display write the data on the parallel inputs are loaded into the registers and no extra steps are needed.
canbus transceiver
MCP2551 minimum component CAN tranceiver. According to the example circuit in the datasheet, the CAN module can be used to connect the unit into a CAN bus if present. The system can have suthority on the bus, or be a listening node.
RS232 interface
The only module besides the MCU to receive uninterrupted power, the RS232 is intended for configuring the system with a PC. Circuit according to Maxim MAX232 datasheet.
Display driver
The display driver is used by SPI interface, and it has the same maximum data clock as the PIC, 10MHz. To get the number of LEDS lit up with 32 bits, the system first writes the address of the required cathode on the line, and as the flip-flops on the display end have registered the correct address, the double word for required leds are thrown in the bus. The A6832 is capable of sourcing 125mA per line, this is about the same as the forward current on non-restricted LED. There's online resistors in the bus just in case, though.
Speed and RPM clock circuitry
This circuit handles the timing of RPM and vehicle speed sensors. Instead of guessing the elapsed time with a program loop counter, this circuit will tell exactly (more or less) the period of RPM and speed signals. The crystal frequency is 32768kHz; this is the frequency used for real time clock circuits. The beauty of it is one second is exactly 2^15 cycles. The circuit for creating clock pulses from a crystal was nicked from Discover Circuits, they had a good one. The clock pulses are delivered into PIC pulse counter by an NPN transistor, which is tied to !Q output pin of a 74112 D-type Flip Flop. While the chip is in reset mode, the pin !Q is high, and the NPN is conductive. There's a 4.7M resistor to limit the base current. The pulses from the speed pickup and coil are put onto the B input pins on the 74360 decade counter. The output pin QA will create a square wave based on the pulse count; the pin is held high from 5 to 9. When the counter rolls over to zero, the output falls low. The flip-flop will detect this and trip; the pin !Q will go low, and the transistor will go non-conductive. Also the output Q will go high, and cause an interrupt on the PIC. Now the PIC will move the counter data into memory, reset the internal counter and send a reset pulse to the JK flip flop for a new batch of pulses. Since the speed difference is vast (40 MHz vs 32 kHz) the PIC should finish the task before the RTC has completed one cycle.
PIC pulse counter rollover happens after two seconds, so it's worth it to run a sanity check here. Let's say lowest reasonable engine RPM you'd expect of a car engine is 600 RPM. That's already 10Hz, and since the coil will fire twice per revolution, the decade counter will roll over every half second. For the vehicle speed, a good estimate is one revolution of the speedometer gauge per half a metre. Since the gauge can display speeds down to 1 unit per hour, it would be reasonable to expect it to do so. 1 km/h is 0.28 m/s, or a full rotation in just a bit under two seconds. For acceptable pulse rate there must be at least ten pulses per rotation.
Finally, the connectors:
The connectors between the car and the CPU are Molex Microclasp connectors, very professional and affordable too (http://www.mouser.com/catalog/629/1185.pdf), unfortunately they're rated only for 3A per pin so they're bit too weak for ECU use (I need to multiply certain pins too).
The connection to gauge panels is via 40-pole ribbon cable, essentially similar to IDE cables. The current capacity is a big issue (With all 32 LEDs powered up, the load is four amps for four lines!). If it gets into a problem, a thicker external wire will be used for LED cathode wire. At first, metallic binder clips are used for heatsinks and the gauge pod will have a chassis fan. The ribbon cable will be quite hot in any case.
The connector for CANbus is standard DE9, and the RS232 is just a header on the circuit board. The idea is the actual connector will be placed somewhere you don't need to take the car apart to access it.
All expansion pin pads are left empty, and will thusmake a sort of veroboard zone on the PCB. There are zones for free CPU pins, SPI channels (with SDI and SDO pins conveniently near by too), analog channels, parallel to serial converter pins, and case connector pins. The number of vacant addresses on the display bus at the moment is eight, so with a led bar and 3x7 display forming an unit there's room for four extra gauges.
It's 5.05AM, I'm tired as hell, but I hope that covered the basics on the CPU in an understandable way. Comments are welcome. Next update will be about the gauge panels. It's a "bit" ambitious project, but I'm hopeful I'm able to build one in the future.