I am trying to implement a POV analog clock like this.
I made it, displayed simple text and patterns successfully but when I got further into displaying complex stuff like text and clock hands at the time, things are getting difficult.
For displaying texts only I started from the sensor readings and displayed the patterns for each line/segment in real time, but when it comes to combining text and patterns I though it would be better to manipulate a 2D array to store graphic information and display it's content after that for each rotation.
That is causing memory problem in Atmega328. If I divide the whole surface of display by 360 the array size will be 360x10(number of LEDs), which is getting bigger than the SRAM(2048 bytes).
I tried to understand the code from the above link, but it's commented in a different language.
How should I approach the problem?
Here is the code
#define HALL_INPUT 2
#define RED_STRIP 4
#define RED1 12
#define RED2 11
#define RED3 10
#define RED4 9
#define RED5 8
#define RED6 7
#define RED7 6
#define BLUE 5
#define WHITE 13
#define SEC_LED 1
/*
* Stores the display matrix
*/
boolean displayMatrix[10][360];
/* Stores time for each rotation in microseconds
* TODO: Make this value dynamic
*/
unsigned long RotationTime = 30500;
unsigned long oneDegTime = RotationTime/360;
void setup() {
pinMode(RED_STRIP, OUTPUT);
pinMode(RED1, OUTPUT);
pinMode(RED2, OUTPUT);
pinMode(RED3, OUTPUT);
pinMode(RED4, OUTPUT);
pinMode(RED5, OUTPUT);
pinMode(RED6, OUTPUT);
pinMode(RED7, OUTPUT);
pinMode(BLUE, OUTPUT);
pinMode(WHITE, OUTPUT);
pinMode(HALL_INPUT, INPUT_PULLUP);
//attachInterrupt(digitalPinToInterrupt(HALL_INPUT), getRotationTime, FALLING);
for(int i = 0; i < 10; i++){
for(int j = 0; j < 360; j++){
displayMatrix[i][j] = false;
}
}
Serial.begin(9600);
}
unsigned long lastCount = 0;
int secCount = 0;
int minCount = 10;
int hourCount = 50;
void loop() {
int interval = 1000;
if(interval < millis() - lastCount){
lastCount = millis();
if(secCount < 60)
secCount++;
else{
secCount = 1;
if(minCount < 60)
minCount++;
else
minCount = 1;
if(minCount == 12 || minCount == 24 || minCount == 36 || minCount == 48 || minCount == 60){
if(hourCount < 60)
hourCount++;
else
hourCount = 1;
}
}
}
clearMatrix();
adjustMatrix(secCount, minCount, hourCount);
if(!digitalRead(HALL_INPUT)){
//testLoop();
displayMat();
/*
Serial.print(hourCount);
Serial.print(" : ");
Serial.print(minCount);
Serial.print(" : ");
Serial.print(secCount);
Serial.println();
*/
}
}
void clearMatrix(){
for(int i = 0; i < 10; i++){
for(int j = 0; j < 360; j++){
displayMatrix[i][j] = false;
}
}
}
void adjustMatrix(int sec, int min, int hour){
for(int i = 0; i < (sec*3); i++){
displayMatrix[SEC_LED][i] = true;
}
}
void displayMat(){
for(int i=0;i<360;i++){
for(int j=0;j<10;j++){
if(displayMatrix[j][i])
writeLED(j, true);
else
writeLED(j, false);
}
delaySegment(1, 360);
}
}
void writeLED(int i, bool state){
if(state){
switch(i){
case 0:
digitalWrite(WHITE, HIGH);
break;
case 1:
digitalWrite(BLUE, HIGH);
break;
case 2:
digitalWrite(RED7, HIGH);
break;
case 3:
digitalWrite(RED6, HIGH);
break;
case 4:
digitalWrite(RED5, HIGH);
break;
case 5:
digitalWrite(RED4, HIGH);
break;
case 6:
digitalWrite(RED3, HIGH);
break;
case 7:
digitalWrite(RED2, HIGH);
break;
case 8:
digitalWrite(RED1, HIGH);
break;
case 9:
digitalWrite(RED_STRIP, HIGH);
break;
}
}
else{
switch(i){
case 0:
digitalWrite(WHITE, LOW);
break;
case 1:
digitalWrite(BLUE, LOW);
break;
case 2:
digitalWrite(RED7, LOW);
break;
case 3:
digitalWrite(RED6, LOW);
break;
case 4:
digitalWrite(RED5, LOW);
break;
case 5:
digitalWrite(RED4, LOW);
break;
case 6:
digitalWrite(RED3, LOW);
break;
case 7:
digitalWrite(RED2, LOW);
break;
case 8:
digitalWrite(RED1, LOW);
break;
case 9:
digitalWrite(RED_STRIP, LOW);
break;
}
}
}
/*
* Displays seconds, minutes and hour
*/
void display(int sec, int min, int hour){
int displaySeq[] = {sec, min, hour};
sort(displaySeq, 3);
digitalWrite(BLUE, HIGH);
digitalWrite(RED6, HIGH);
digitalWrite(RED1, HIGH);
digitalWrite(RED2, HIGH);
int delayedMicros = 0;
for(int i = 0; i < 3; i++){
delaySegment(displaySeq[i] - delayedMicros, 60);
delayedMicros = displaySeq[i];
if(displaySeq[i] == sec)
digitalWrite(BLUE, LOW);
if(displaySeq[i] == min)
digitalWrite(RED6, LOW);
if(displaySeq[i] == hour){
digitalWrite(RED1, LOW);
digitalWrite(RED2, LOW);
}
}
}
/*
* Handles the delay in microseconds smoothly
* @params
* int num: Number of segemnts to delay
* int divisor: Total number of segments
*/
void delaySegment(int num, int divisor){
unsigned int segmentLength = RotationTime/divisor;
if(segmentLength*num < 16000)
delayMicroseconds(segmentLength*num);
else{
delayMicroseconds(segmentLength*num/2);
delayMicroseconds(segmentLength*num/2);
}
}
/*
* Performs a selection sort
* @params
* int arr[]: The array
* int len: Length of the array
*/
void sort(int arr[], int len){
int temp, pos;
for(int i = 0; i < len - 1; i++){
pos = i;
for(int j = i + 1; j < len; j++){
if(arr[pos] > arr[j])
pos = j;
}
if(pos != i){
temp = arr[i];
arr[i] = arr[pos];
arr[pos] = temp;
}
}
}
/*
* Displays fours bars at 90 deg interval
*/
void displayClock(){
delayMicroseconds(oneDegTime*44);
digitalWrite(BLUE, HIGH);
delayMicroseconds(oneDegTime*2);
digitalWrite(BLUE, LOW);
delayMicroseconds(oneDegTime*88);
digitalWrite(BLUE, HIGH);
delayMicroseconds(oneDegTime*2);
digitalWrite(BLUE, LOW);
delayMicroseconds(oneDegTime*88);
digitalWrite(BLUE, HIGH);
delayMicroseconds(oneDegTime*2);
digitalWrite(BLUE, LOW);
delayMicroseconds(oneDegTime*88);
digitalWrite(BLUE, HIGH);
delayMicroseconds(oneDegTime*2);
digitalWrite(BLUE, LOW);
delayMicroseconds(oneDegTime*44);
}
/*
* Display a circle to test out the speed
*/
void testLoop(){
digitalWrite(BLUE, HIGH);
digitalWrite(WHITE, HIGH);
delayMicroseconds(180*oneDegTime);
delayMicroseconds(180*oneDegTime);
digitalWrite(BLUE, LOW);
digitalWrite(WHITE, LOW);
}
/*
* External Interrupt function: Calcutates the time for each rotation and store it in RotationTime
* TODO: Use later
*/
unsigned long prevRotationTime = 0;
void getRotationTime(){
RotationTime = millis() - prevRotationTime;
prevRotationTime = millis();
}
There are some extra functions that is used earlier and not used currently.