Popis
Zobrazení na LED displeji je zařízeno dvěma posuvnými 8-mi bitovými registry 74HC595, kdy jeden slouží ke spínání segmentů na jednom znaku a druhý ke spínání jednotlivých znaků (v tomto zapojení je využito pouze 4 bitů, takže druhá polovina může ovládat další LED). Je použit LED se společnou katodou (GND). Z důvodu malého proudu z pinů arduina je nutné spínat LED přes tranzistory (např. BC547).
Obvod
Příklad kódu
V tomto příkladu je využita knihovna TimerOne.
#include <TimerOne.h>
const int pinLatch = 9;
const int pinClock = 8;
const int pinData = 10;
const int BUFFER_SIZE = 10;
const int DISPLAY_LENGTH = 4;
byte disp[DISPLAY_LENGTH];
byte decimalPointIndex = 255;
byte digits[] = {
B00111111, //0
B00000110, //1
B01011011, //2
B01001111, //3
B01100110, //4
B01101101, //5
B01111101, //6
B00100111, //7
B01111111, //8
B01101111 //9
};
float numbers[] = {
765.4,
765.912,
123,
56.0,
78.1,
12.34,
64.345,
98,
1.4,
5.0,
0.789,
0.1,
.88,
.123,
.4567,
3.7891
};
int numberIndex = 0;
void setup() {
Serial.begin(9600);
Timer1.initialize(10000);
pinMode(pinLatch, OUTPUT);
pinMode(pinClock, OUTPUT);
pinMode(pinData, OUTPUT);
setNumber(0);
Timer1.attachInterrupt(showNumber);
}
void loop() {
noInterrupts();
setNumber(numbers[numberIndex]);
Serial.println("OK");
Serial.println(numbers[numberIndex], DEC);
interrupts();
numberIndex++;
if (numberIndex > 15)
numberIndex = 0;
delay(2000);
}
void showNumber() {
byte show = 0;
for (int i = 0; i < DISPLAY_LENGTH; i++) {
byte value = digits[disp[i]];
if (decimalPointIndex == i) value |= 128;
shiftOut(pinData, pinClock, MSBFIRST, (disp[i] > 9 || disp[i] < 0) ? B00000000 : value);
shiftOut(pinData, pinClock, MSBFIRST, B00000001 << i);
digitalWrite(pinLatch, LOW);
digitalWrite(pinLatch, HIGH);
delayMicroseconds(1000);
}
shiftOut(pinData, pinClock, LSBFIRST, 0);
shiftOut(pinData, pinClock, LSBFIRST, ~0);
digitalWrite(pinLatch, LOW);
digitalWrite(pinLatch, HIGH);
}
void setNumber(float number) {
if (number >= 10000 || number < 0) return;
byte num[BUFFER_SIZE];
byte dec[BUFFER_SIZE];
byte numCount = 0;
byte decCount = 0;
getWholeNumbers(number, num, numCount);
getDecimals(number, dec, decCount, 4); // find decimal point
decimalPointIndex = (byte) 255;
for (int i = 0; i < DISPLAY_LENGTH; i++) {
disp[i] = (byte) 255;
}
if (number >= 1000.0) {
for (int i = 0; i < DISPLAY_LENGTH; i++) {
disp[i] = num[i];
}
} else if (number >= 100) {
int startIndex = 1;
if (decCount > 0) {
decimalPointIndex = 2;
startIndex = 0;
disp[3] = dec[0];
}
for (int i = 0; i < 3; i++) {
disp[i + startIndex] = num[i];
}
} else if (number >= 10) {
int startIndex = 2;
if (decCount > 0) {
int maxDecLength = DISPLAY_LENGTH - numCount;
int numberOfDP = (maxDecLength < decCount) ? maxDecLength : decCount;
startIndex = maxDecLength - numberOfDP;
for (int i = 0; i < numberOfDP; i++) {
disp[i + startIndex + 2] = dec[i];
}
decimalPointIndex = (byte)(startIndex + 1);
}
for (int i = 0; i < 2; i++) {
disp[i + startIndex] = num[i];
}
} else {
int startIndex = 3;
if (decCount > 0) {
int maxDecLength = DISPLAY_LENGTH - numCount;
int numberOfDP = (maxDecLength < decCount) ? maxDecLength : decCount;
startIndex = maxDecLength - numberOfDP;
for (int i = 0; i < numberOfDP; i++) {
disp[i + startIndex + 1] = dec[i];
}
decimalPointIndex = (byte)(startIndex);
}
for (int i = 0; i < 1; i++) {
disp[i + startIndex] = num[i];
}
}
}
void getWholeNumbers(float value, byte pData[], byte & count) {
byte n[BUFFER_SIZE];
int p = (int) value;
int l = 1;
for (int i = 0; i < BUFFER_SIZE; i++) {
n[i] = (byte)(p % 10);
p -= n[i];
if (p > 9)
l++;
p /= 10;
}
count = l;
for (int i = 0; i < l; i++) {
pData[i] = n[l - 1 - i];
}
}
void getDecimals(float value, byte pData[], byte & count, int maxCount) {
byte n[BUFFER_SIZE];
float f = value;
for (int i = 0; i < BUFFER_SIZE; i++) {
if (i >= maxCount) {
n[i] = 0;
} else {
f *= 10;
n[i] = (byte)(fmod(f, 10));
}
}
int len = 0;
for (int i = 0; i < BUFFER_SIZE; i++) {
if (n[BUFFER_SIZE - 1 - i] == 0) continue;
len = BUFFER_SIZE - i;
break;
}
count = len;
for (int i = 0; i < len; i++) {
pData[i] = n[i];
}
}
Soubory