Not bad! I would do the same if I needed scrolling text. I don't so I wrote some code that takes input by pressing up an down buttons to cycle through all possible inputs. Enter to confirm I also made a text input area where you use left and right to move cursor around and you can type in messages like hello all. But it takes some time since the input is character by character and I spent a lot of time pressing the up and down buttons to get different letters. It's included in my Morse code in/output program on my blog.
@qliudr
You can be sure that I had a closer look to your source code. Very fine but it took some time to understand it 8), but I didn't manage until now to get it running on my configuration (different shield etc. ) But I will try even more.
What I took as an inspiration from your project is the use of the buttons. My shield can only show 16x2 characters and that is not enough for a tweet. So the next step will be a double array 16x10 so that I can keep the whole message and after morse output I can scroll with the keys through the message.
You can see the scrolling lines on my http://hajos-kontrapunkte.blogspot.com/2011/02/morsetweeter-v-08.html.
I don't understand, there is a lot examples inside the LiquidCrystal440.h example.
Here is some...
#include <LiquidCrystal.h>
LiquidCrystal lcd(8, 9, 4, 5, 6, 7); // replace with your PIN configuration
int nRows = 2; // n of LCD's rows
int nColumns = 16; // n of LCD's columns
void setup() {
lcd.clear();
lcd.begin(nColumns, nRows); // 16 ROWS / 2 LINES
}
void loop() {
//======setCursor===
// loop from ASCII 'a' to ASCII 'z':
lcd.home();
int thisLetter = 'a';
// loop over the rows:
for (int thisRow = 0; thisRow < nRows; thisRow++) {
// loop over the columns:
for (int thisCol = 0; thisCol < nColumns; thisCol++) {
// set the cursor position:
lcd.setCursor(thisCol,thisRow);
// print the letter:
lcd.print(thisLetter, BYTE);
thisLetter++;
if (thisLetter > 'z') thisLetter = 'a';
delay(100);
}
}
//========Autoscroll: -- my arch nemesis !
lcd.clear();
// set the cursor to (0,0):
lcd.setCursor(0, 0);
// print from 0 to 9:
lcd.print("Autoscroll");
for (char thisChar = '1'; thisChar < '9'; thisChar++) {
lcd.print(thisChar);
delay(100);
}
// set the cursor to (nColumns,1):
lcd.setCursor(0,1);
lcd.print("Autoscroll");
// set the display to automatically scroll:
lcd.autoscroll();
// print from 0 to 9:
for (int thisChar = 0; thisChar < 10; thisChar++) {
lcd.print(thisChar);
delay(100);
}
// turn off automatic scrolling
lcd.noAutoscroll();
if (nRows>2) {
//========Autoscroll: -- my arch nemesis !
// set the cursor to (0,0):
lcd.setCursor(0, nRows-2);
// print from 0 to 9:
lcd.print("Autoscroll");
for (char thisChar = '1'; thisChar < '9'; thisChar++) {
lcd.print(thisChar);
delay(100);
}
// set the cursor to (nColumns,1):
lcd.setCursor(0,nRows-1);
lcd.print("Autoscroll");
// set the display to automatically scroll:
lcd.autoscroll();
// print from 0 to 9:
for (int thisChar = 0; thisChar < 10; thisChar++) {
lcd.print(thisChar);
delay(200);
}
// turn off automatic scrolling
lcd.noAutoscroll();
}
}
You are right of course. But I wanted to push up the second line on the first and continue to write on the second line. So I had to erase the first, copy the second to the first, erase the 2. and continue to write on the second.
LeseLaster: @qliudr
You can be sure that I had a closer look to your source code. Very fine but it took some time to understand it 8), but I didn't manage until now to get it running on my configuration (different shield etc. ) But I will try even more.
You could, you know, buy my shield and save the trouble
It's got clock, eeprom, and GPS besides an onboard buzzer so saves your breadboard.
Nice video. I'm not expert in Morse code, expecially not when I had to translate from Morse into Germain then into English
Yes, my code is not the easiest to understand but I built those functions for very different projects and in layers so I can update one particular layer without disturbing the rest. The Morse in and out should be relatively straight-forward. Let me know how your project goes. I'm very happy if my code runs on the other side of the globe 8)
LeseLaster:
I wanted to push up the second line on the first and continue to write on the second line. So I had to erase the first, copy the second to the first, erase the 2. and continue to write on the second....Anyway I found some other useful code
Instead of "finding" some code why not just implement your scheme as you articulated it. I mean, my observation is that the hardware "autoscroll" function hardly ever does what people think it should do, but doing things like you need in software is straightforward.
Maybe something like the following
//
// Simple line-by-line scrolling for LCD with two rows
//
// davekw7x
//
#include <LiquidCrystal.h>
const int NROWS = 2;
const int NCOLS = 16;
LiquidCrystal lcd(7, 6, 5, 4, 3, 2); // Customize for your connections.
void setup()
{
lcd.begin(NCOLS, NROWS); // This clears the LCD
lcd.setCursor(0, 1); // Start on the second row
}
int counter = 1;
void loop()
{
char buffer[17];
sprintf(buffer, " Loop %d: ", counter);
sendmsg(buffer);
++counter;
for (char alpha = 'a'; alpha <= 'z'; ++alpha) {
buffer[0] = alpha;
buffer[1] = '\0';
sendmsg(buffer);
delay(300);
}
delay(2000);
}
void LcdClearLine(int r)
{
lcd.setCursor(0,r);
for (int i = 0; i < NCOLS; i++) {
lcd.print(" ");
}
}
char line[NCOLS];
char col; // The compiler makes sure this is initialized to zero.
void sendmsg(char *str)
{
while (*str) {
if (col >= 16) {
//Serial.println("Scrolling"); // Uncomment for debugging
// Print the line contents to the first row
lcd.setCursor(0, 0);
for (int i = 0; i < NCOLS; i++) {
lcd.print(line[i]);
}
LcdClearLine(1); // Spaces to second row
lcd.setCursor(0, 1); // set cursor to beginning of second row
col = 0;
}
line[col] = toupper(*str);
lcd.print(line[col++]);
++str;
}
}
Regards,
Dave
Footnote:
"quasi-code" for the functionality could be added as comments:
Suppose we have an LCD that has two rows. Each row has NCOLS
columns.
Here is a way to scroll the way that you indicated
/*
There is a static array that holds characters of
the current line:
*/
char line[NCOLS];
/*
There is a static integer used to keep track of the
column position for the next character. This is
also used as an index to store the character in
the array.
*/
int col; // Initialized to zero
/*
sendmsg gets a pointer to char (the "string pointer")
For each character in the "string," here's what the function
does:
1.
If the array is full (col equal to NCOLS), it copies the
contents of the array to the first line of the the LCD and
clears the second line of the LCD. It sets col to zero
2.
It stores the character in the array and prints the char
to the LCD.
3.
It increments the column counter and it increments the "string pointer"
*/
Thanks for the pseudo-code and the real one. I learned:
internal variables,
predeclared functions
...
Still have problems with pointer and why you have filled the buffer[17] with buffer[1] = '\0';
I thought that was not needed for the LCD.
No excuse, but I stopped about 15 years ago programming in Smalltalk and Prolog and started now again with C. So going is slow and I learn quicker by example when I am unsure about the syntax.
Thanks for the pseudo-code and the real one. I learned:
internal variables,
predeclared functions
...
Still have problems with pointer and why you have filled the buffer[17] with buffer[1] = '\0';
I thought that was not needed for the LCD.
No excuse, but I stopped about 15 years ago programming in Smalltalk and Prolog and started now again with C. So going is slow and I learn quicker by example when I am unsure about the syntax.
Again thanks for your help.
It is because a C string needs to be zero-terminated. Does that ring a bell? If a string is not terminated, the print doesn't know when to stop printing and will continue to print beyond the string and read sections of memory that's totally not string so you will get junk and sometimes freeze up. If you define a string like char a[]="hello"; the compiler helps you attach a zero in the end.
Good approach! In the 90s when I was experimenting on 386 assembly i got blue screen (prior to windows there were no blue screen but I intend to use this expression for cpu freeze) very often
The loop in sendmsg (from your code) uses the zero byte to know when it has reached the end of the "string." That's the way that "normal" C library functions handle these things, and it is a convention followed by C programmers everywhere (well, almost everywhere).
Here's the loop:
while (*str) {
.
.
.
++str;
}
That means that the pointer is incremented each time through the loop. When the pointer reaches the address of the zero byte, the "while" condition fails, and that's the end of the road. The calling function puts a single character at the beginning of the buffer, followed by a zero byte, every time my program called the function. That's just an example. You could put any kind of C-style "string" in the buffer (always terminated by a zero byte).
My misunderstanding came from the way I wanted to implement the storage of chars. In the first go I wanted /want to use a two dimensional array (matrix) (something like char lines [16] [10]) so that I am able to retrieve a longer text on the display via the buttons on the LCD shield. The control of the matrix should be done by loops. I was not aware that a transition from "normal" array to string was triggered.
Now I see that it is easier to go with strings incl. termination. Oh dear, perhaps I should have stayed with things I know how to handle.