right now im working on dot matrix clock, able to display some scrolling text depending on the time.
Hardware used: arduino uno r2, 2x sure 8x32 matrix displays (ht1632c), ds1307 based RTC. Arduino IDE 1.0.5-r2.
Currenty im using this code and it is working just fine, but im pretty sure there is a much more elegant solution for this function. Besides its a pain in the ass to modify the whole "what text to show to which time" thing.
#include <HT1632.h>
#include <font_8x4.h>
char t1200 [] = "some text 1";
char t1230 [] = "some text 2";
char display [] = "hh:mm:ss";
//some RTC functions.....................
//initialising the matrix
void setup () {
HT1632.begin(12, 13, 11, 10); // (CS1, CS2, WR, DATA)
//printing the text to the dot matrix
void loop () {
int hh = hour;
int mm = minute;
int ss = second;
//replacing time with predifined text
if (hh == 12 && mm == 0)
{
sprintf(display, t1200);
wd = HT1632.getTextWidth(t1200, FONT_8X4_END, FONT_8X4_HEIGHT);
}
else if (hh == 12 && mm == 30)
{
sprintf(display, t1230);
wd = HT1632.getTextWidth(t1230, FONT_8X4_END, FONT_8X4_HEIGHT);
}
else
{
sprintf(display, "%02d:%02d:%02d", hh, mm, ss);
wd = HT1632.getTextWidth(disp, FONT_8X4_END, FONT_8X4_HEIGHT);
}
HT1632.renderTarget(0);
HT1632.clear();
HT1632.drawText(display, OUT_SIZE * 2 - i, 0, FONT_8X4, FONT_8X4_END, FONT_8X4_HEIGHT);
HT1632.render();
HT1632.renderTarget(1);
HT1632.clear();
HT1632.drawText(display, OUT_SIZE - i, 0, FONT_8X4, FONT_8X4_END, FONT_8X4_HEIGHT);
HT1632.render();
i = (i+1)%(wd + OUT_SIZE * 2);
delay(100);
}
That's not how to use sprintf. You must provide a character buffer long enough for all
situations - sprintf modifies this buffer (it sets a null at the end).
As your code is written it corrupts memory as t1200 is longer than display.
Thank you for your answer. My C knowledge is less than basic, im not really getting your reference. Would you be so kind and give me a example using my variables?
MarkT:
You are overwriting memory because t1200 and t1230 are both longer than display.
Why are you trying to use sprintf with these strings at all? Just pass the right string
to drawText in the first place?
And you haven't declared disp.
Im trying to keep the code as minimal as possible. By inserting drawText into the if loop there will be 8 lines of code more then right now. Above i posted the full code.
Concerning disp, you are right it should be display.
Thank you Nick! It does work perfectly. Now there is only one line per text replacement inside the if loop. The getTextWidth function is also mentioned once. That makes the code easyer to modify.
This is what the final version looks like:
char t1200 [] = "some text 1";
char t1230 [] = "some text 2";
char display [33] = "hh:mm:ss";
//some code here
//.
//.
//.
//.
void loop () {
//Matrix brightness 16 steps 1-16 (max L =1024 min L = 0)
L = analogRead(LIn);
Serial.print("brightness ");
Serial.print(L/64+1);
Serial.print(" ");
HT1632.setBrightness((L/64+1), 0b0011);
int hh = hour;
int mm = minute;
int ss = second;
int DD = dayOfMonth;
int MM = month;
int YY = year;
int WD = dayOfWeek;
//Magic starts here
if (hh == 12 && mm == 0)
{
sprintf(display, t1200);
}
else if (hh == 12 && mm == 30)
{
sprintf(display, t1230);
}
else
{
sprintf(display, "%02d:%02d:%02d", hh, mm, ss);
}
wd = HT1632.getTextWidth(display, FONT_8X4_END, FONT_8X4_HEIGHT);
HT1632.renderTarget(0);
HT1632.clear();
HT1632.drawText(display, OUT_SIZE * 2 - i, 0, FONT_8X4, FONT_8X4_END, FONT_8X4_HEIGHT);
HT1632.render();
HT1632.renderTarget(1);
HT1632.clear();
HT1632.drawText(display, OUT_SIZE - i, 0, FONT_8X4, FONT_8X4_END, FONT_8X4_HEIGHT);
HT1632.render();
i = (i+1)%(wd + OUT_SIZE * 2);
delay(100);
getDateDs1307();//get the time data from tiny RTC;
}
But that's perverse - just pass the string you want to see to drawText, rather than copying it
into display. The sprintf to set display is done to convert the time to a string, using sprintf
to copy a fixed string is opaque and confusing.
We were explicitly asked for the elegant solution....