To review, I am making a digital tachometer that looks like this:
To drive the 7 segment LEDs, I am using a MAX7219, and for the bar graph around the perimeter, I'm using 5 PCA9922s, which are shift registers similar to 74HC595s but higher power (and different pinouts). There are also three LEDs to backlight the "RPM" nomenclature and are driven by spare outputs of one of the PCA9922s. After experimenting with the AS4 simulator and trying different ideas writing code, I have frozen the hardware design of my tachometer.
|=============================================================================| | | | ATtiny 26 Microcontroller | | | | +----v----+ | | MOSI/PB0 -| 1 20 |- PA0/ADC0 Analog Dimmer Input | | MAX7219 Data Out MISO/PB1 -| 2 19 |- PA1/ADC1 | | Serial Clock SCK/PB2 -| 3 18 |- PA2/ADC2 | | Crank Sensor Input PCINT0/PB3 -| 4 17 |- PA3/AREF Capacitor to ground | | VCC -| 5 16 |- GND | | GND -| 6 15 |- AVCC | | 16 mHz crystal XTAL1/PB4 -| 7 14 |- PA4/ADC3 MAX7219 Select/Latch | | 16 mHz crystal XTAL2/PB5 -| 8 13 |- PA5/ADC4 PCA9922 Select/Latch | | T0/PB6 -| 9 12 |- PA6/ADC5 | | Reset RESET/PB7 -| 10 11 |- PA7/ADC6 PCA9922 data out | | +---------+ | | | ===============================================================================
Through my experimenting I found the USI is the most efficient way to send data to the MAX7219. But the bar graph is another story. Breaking the serial stream into 8 bit (single byte) chunks is quite cumbersome. I need to send 40 bits in series. Since it is a bar graph, there is a series of continuous ones followed by a series of zeros. I'll use a loop to count through the ones then the zeros. This takes more clock cycles that I expected in the loop, but is is way better than breaking the 40 bits into 5 bytes. I'll use the USI clock for the PCA9922 even though the data is output from a different pin than the USI data. The USI clock toggles with one clock cycle while an I/O pin takes two. As discussed in previous threads, on the bar graph, I plan to use software PWM to vary the intensity of the top lit segment to do a kind of 'interpolation' between segments. It is a kind of anti-aliasing for the top segment (if that makes sense). I am using an external analog signal to define the LED intensity for overall dimming at night (just like the way the dimming in a car works). This will be easy with the MAX7219. But since the bar graph top segment uses PWM, I need to make sure the whole program runs fast enough to provide enough granularity so I can do both overall intensity AND top segment PWM. The crank sensor input uses the Pin Change Interrupt to count edges from 40 'holes' (80 edges) in a disk (flywheel). I count these edges for .075 secs. This gives one tenth the RPM (ie. at 2500 RPM = 250 counts). If I want more resolution, I found that I can average, say, ten readings, but NOT divide by ten. In this thread, I will be sharing the step-by-step assembly of the whole project. I have a small machine shop (including CNC) and will be custom building the enclosure, LED diffuser, engraved face, etc. So I'll show all that along with the code development and testing. I have already completed the diffuser and engraved face, so in my next few posts, I'll show the process of fabricating them. Plus, I should have PCBs in a few weeks, so stay tuned.... This forum has been such a great help to my being able to even do this, I think it will be a way for all that helped to see the fruit of their efforts (since this has DEFINITELY been a team effort). It is also a way for me to thank Kartman, clawson, bobgardner, joeymorin, et al.... I don't know if this is the proper forum, so forgive me if it isn't. :wink: Cris