Text Scrolling Loop??

Good Day Everyone,

Im fairly new at this, so I'm taking it one step at a time.

My question is this.... Im designing a controller for Antenna Rotators. The Rotator has a 0-500 Ohm potentiometer that indicates its direction. 0 and 500 Ohm being North. I have the display setup to indicate the direction using a compass heading display. Like below:

N.....E.....S.....W.....

Iv searched, for a way to get the text to scroll left or right associated with the rise or fall of the resistance from the potentiometer. AND have it infinitely scroll. so that when it scrolls to the left, the text falls of of the left side of the screen, and re-appears on the right side. as if its a loop of text.

Any help is appreciated. Thank you.

Nudatech.com has a scrolling lcd project.
http://www.nudatech.com/scrolling_text_on_LCD_with_pushbuttons?search=scrolling%20lcd
It uses pushbuttons to scroll left , scroll right.
Obviously you can rewire it to use a digital output to simulate the button press.
They have a funny system setup whereby if you want to download their project (which is free) you have to
add it to your cart and "buy" it for $0.00.
I attached the program but you need to look at their circuit and all so you can get the code from their page.
I breadboarded it and it worked fine.

nudatechlcd_2.ino (3.21 KB)

If it Helps... Here is my current code.

// Amateur Radio Antenna Rotator Controller
// 
// Original code by John Brent (VA3WPN)

#include <Wire.h>
#include <LiquidCrystal_I2C.h>
  
LiquidCrystal_I2C lcd(0x20,20,4);  // set the LCD address to 0x20 for a 20 chars and 4 line display

byte headN[8] = { B10001, B11001, B10101, B10011, B10001, B00100, B00100, B00100 }; // North Marker
byte headE[8] = { B01110, B01000, B01110, B01000, B01110, B00100, B00100, B00100 }; // East Marker
byte headS[8] = { B01110, B01000, B01110, B00010, B01110, B00100, B00100, B00100 }; // South Marker
byte headW[8] = { B10001, B10101, B10101, B01010, B01010, B00100, B00100, B00100 }; // West Marker
byte headA[8] = { B00000, B00000, B00000, B00100, B00100, B10101, B01110, B00100 }; // Heading Arrow

void setup()

{
  lcd.init();                      // initialize the lcd 
  lcd.backlight();

// Heading
  lcd.createChar(0, headA); // Defines Heading Arrow
  lcd.createChar(1, headN); // Defines North Marker
  lcd.createChar(2, headS); // Defines South Marker
  lcd.createChar(3, headE); // Defines East Marker
  lcd.createChar(4, headW); // Defines West Marker

  lcd.setCursor(9, 1);
  lcd.print("360");  // Displays Heading in Degrese
  lcd.setCursor(10, 2);
  lcd.write(0);  // Heading Indicator
  lcd.setCursor(0, 3);
  lcd.write(2); // South
  lcd.print("....");
  lcd.write(4); // West
  lcd.print("....");
  lcd.write(1);  // North
  lcd.print("....");
  lcd.write(3); // East
  lcd.print("....");

// Station Info
  lcd.setCursor(0, 0);
  lcd.print("CALL"); // Sets Callsign of Station
  lcd.setCursor(15, 0);
  lcd.print("19:30");  // Displays Time

}

void loop()
{

}

That's probably not necessary. The Nudatech program has text that you can replace with yours
and control the left and right scrolling any way you want by replacing the pushbuttons with digital outputs.
Your project is a great application for this technology.
Best of luck with it.

raschemmel:
That's probably not necessary. The Nudatech program has text that you can replace with yours
and control the left and right scrolling any way you want by replacing the pushbuttons with digital outputs.
Your project is a great application for this technology.
Best of luck with it.

Thank you, this is just one portion of the code.

This project Im hoping will be useable by many other Ham's who have Rotators... but use outdated controllers.

If you don't mind me asking, Why a loop?
Why not an interupt ?
What determines the rotator location ?
Is that a HW feedback loop tracking signal strength ?
How do plan to interface the rotator with the arduino ?
Were you striving for the "look and feel" of a marine navigation
compass with a virtual 360 degrees with 90 degrees visable
on the LCD at all times, scrolling left and right ? (45,

45)

So... Iv got the code written to use the Pot's resistance as the input to change the heading and the compass setting. And its working... how ever the text does not loop on the same line, it goes up to the top line. Below is my code updated.

// Amateur Radio Antenna Rotator Controller
// 
// Original code by John Brent (VA3WPN)

#include <Wire.h>
#include <LiquidCrystal_I2C.h>
  
LiquidCrystal_I2C lcd(0x20,20,4);  // set the LCD address to 0x20 for a 20 chars and 4 line display

byte headN[8] = { B10001, B11001, B10101, B10011, B10001, B00100, B00100, B00100 }; // North Marker
byte headE[8] = { B01110, B01000, B01110, B01000, B01110, B00100, B00100, B00100 }; // East Marker
byte headS[8] = { B01110, B01000, B01110, B00010, B01110, B00100, B00100, B00100 }; // South Marker
byte headW[8] = { B10001, B10101, B10101, B01010, B01010, B00100, B00100, B00100 }; // West Marker
byte headA[8] = { B00000, B00000, B00000, B00100, B00100, B10101, B01110, B00100 }; // Heading Arrow

void setup()

{
  lcd.init();                      // initialize the lcd 
  lcd.backlight();
  
// Station Info
  lcd.setCursor(0, 0);
  lcd.print("CALL"); // Sets Callsign of Station
  lcd.setCursor(15, 0);
  lcd.print("19:30");  // Displays Time

}

void loop()
{
  setHeading(375);
}

void setHeading(int x)
{
  int Heading;
  int CR;
  
  Heading = x/1.388;
  CR = x/25;
  
  lcd.createChar(0, headA); // Defines Heading Arrow
  lcd.createChar(1, headN); // Defines North Marker
  lcd.createChar(2, headS); // Defines South Marker
  lcd.createChar(3, headE); // Defines East Marker
  lcd.createChar(4, headW); // Defines West Marker

  lcd.setCursor(9, 1);
  lcd.print(Heading);  // Displays Heading in Degrese
  lcd.setCursor(10, 2);

  lcd.write(0);  // Heading Indicator

  lcd.setCursor(CR, 3);
  lcd.write(2); // South
  lcd.print("....");
  lcd.write(4); // West
  lcd.print("....");
  lcd.write(1);  // North
  lcd.print("....");
  lcd.write(3); // East
  lcd.print("....");
}

raschemmel:
If you don't mind me asking, Why a loop?
Why not an interupt ?

Im not sure I follow this question.. I mean as to loop around the display on a single line. As if its continuous.

What determines the rotator location ?

Thre is a Potentiometer in the Rotator, that has a calibrated resistance from 0 to 500 Ohms. This is asociated with the direction its pointing. Ie. 0/500 is North, 125 is East, 250 is South, and 375 is West.

Is that a HW feedback loop tracking signal strength ?

See Above

How do plan to interface the rotator with the arduino ?

The Arduino will move the rotator via a relay system. It will use the built in pot to limit rotation, as well as calculate its posision.

Were you striving for the "look and feel" of a marine navigation
compass with a virtual 360 degrees with 90 degrees visable
on the LCD at all times, scrolling left and right ? (45,

45) [/quote]

Yes, how ever the full 360 is visable, and the scale slips from left to right and an Indicator point lays on the heading in the center of the screen.

Cool.
Ok, I got it.

Here is my latest code, if anyone is interested in helping move this forward.

/* Amateur Radio Antenna Rotator Controller

   Powered by Arduino Uno Rev. 3

   Using I2C 20 x 4 LCD Display
   * 5v  -- Vcc
   * Gnd -- Gnd
   * A4  -- SDA
   * A5  -- SCL
      
   Under Development
   
   Original code by John Brent (VA3WPN)
*/

#include <Wire.h>
#include <LiquidCrystal_I2C.h>
  
LiquidCrystal_I2C lcd(0x20,20,4);  // set the LCD address to 0x20 for a 20 chars and 4 line display

byte headN[8] = { B10001, B11001, B10101, B10011, B10001, B00100, B00100, B00100 }; // North Marker
byte headE[8] = { B01110, B01000, B01110, B01000, B01110, B00100, B00100, B00100 }; // East Marker
byte headS[8] = { B01110, B01000, B01110, B00010, B01110, B00100, B00100, B00100 }; // South Marker
byte headW[8] = { B10001, B10101, B10101, B01010, B01010, B00100, B00100, B00100 }; // West Marker
byte headA[8] = { B00000, B00000, B00000, B00100, B00100, B10101, B01110, B00100 }; // Heading Arrow

void setup()

{
  lcd.init();                      // initialize the lcd 
  lcd.backlight();

  lcd.setCursor(1, 1);
  lcd.print("Rotator Controller"); // Sets Callsign of Station
  lcd.setCursor(6, 2);
  lcd.print("V1.0 Beta");  // Displays Time
  delay(30

Im still not able to get the bottom line to wrap to its self.

Maybe it would help if you describe your current test setup and explain how you are measuring the pot with an Arduino.
Since you have some math:

  setHeading(375);
}

void setHeading(int x)
{
  int Heading;
  int CR;
  
  Heading = x/1.388;
  CR = x/25;

but are not showing how you get measure the pot or how you get that info into your equation, maybe it would
help if you explain that , and whether or not you are using any debug methods like Serial print commands.

BTW,
ADD CODE TAGS explaining the code (COMMENTS) to ANY code you post. That is a forum standard requirement.

And its working... how ever the text does not loop on the same line, it goes up to the top line.

Im still not able to get the bottom line to wrap to its self.

Maybe you can get some ideas by learning more about how the memory in the LCD controller is configured. It's probably going to involve some fancy cursor positioning. Follow the LCD Addressing link at http://web.alfredstate.edu/weimandn to find out more than you probably want to know.

Don

Thanks , I could find that useful too.

Okay, so... Maybe a little more on my testing setup.

I am using a 500 Ohm potentiometer to simulate the same device that is built into the rotator. The potentiometer in the rotator is what gives the rotator its heading. When the potentiometer is at 0 or 500 ohms, it is pointing north. Using a calculation of Ohms/1.388 you get a result that is between 0 and 360. this associates to the degrees on a compass thus a heading.

I am displaying this information via an I2C 20 x 4 display. And this is where my problem comes into play....

My primary issue at this point is that the bottom line... has a compass heading on it.. like this

CALL 19:30
270
|
S.....W.....N.....E.....

The bottom line needs to scroll left and right, to corrispond with the heading above it. This I can achieve. The problem is.. that when that (S.....W.....N.....E.....) Scrolls to the left it scrolls up onto line 2 from the right. When it scrolls to the right it scrolls up onto line 1 from the left.

I my goal is to have that (S.....W.....N.....E.....) scroll around on its self as if it is one big loop, on a single line. Thus giving the display of a naval, or guidance heading.

Here is a copy of my current, and very commented code.

/* Amateur Radio Antenna Rotator Controller
 
 This is a beta version, very very basic. Its intended to be used as a testing and learning platform for myself.
 Hopfuly it will help others with some of the problems and milestones I have been facing.
 
 Powered by Arduino Uno Rev. 3

 I2C 20 x 4 LCD Display
   * 5v  -- Vcc
   * Gnd -- Gnd
   * A4  -- SDA
   * A5  -- SCL

 Potentiometer
   * 5v  -- Pwr
   * Gnd -- GND
   * A0  -- Wiper
   
 Original code by John Brent (VA3WPN) 2014 */

#include <Wire.h>
#include <LiquidCrystal_I2C.h>

int headPin = 0; // Pin connected to heading pot wiper
int potHead;     // Variable to read heading pot value
  
LiquidCrystal_I2C lcd(0x20,20,4);  // set the LCD address to 0x20 for a 20 chars and 4 line display

byte headN[8] = { B10001, B11001, B10101, B10011, B10001, B00100, B00100, B00100 }; // North Marker
byte headE[8] = { B01110, B01000, B01110, B01000, B01110, B00100, B00100, B00100 }; // East Marker
byte headS[8] = { B01110, B01000, B01110, B00010, B01110, B00100, B00100, B00100 }; // South Marker
byte headW[8] = { B10001, B10101, B10101, B01010, B01010, B00100, B00100, B00100 }; // West Marker
byte headA[8] = { B00000, B00000, B00000, B00100, B00100, B10101, B01110, B00100 }; // Heading Arrow

void setup()

{
  Serial.begin(9600);
  lcd.init();                      // initialize the lcd 
  lcd.backlight();                 // Turns on the back light

  lcd.setCursor(1, 1);
  lcd.print("Rotator Controller"); // Sets Callsign of Station
  lcd.setCursor(6, 2);
  lcd.print("V1.0 Beta");          // Displays Time
  delay(3000);
  lcd.clear();
  
// Station Info
  lcd.setCursor(0, 0);             // Sets cursor to callsign posision
  lcd.print("CALL");               // Sets Callsign of Station
  lcd.setCursor(15, 0);            // Sets cursor to time posision
  lcd.print("19:30");              // Displays Time

}

void loop()
{
  potHead = analogRead(headPin);              // Reads the value of the heading pot
  potHead = map(potHead, 0, 686, -360, 360);  // Maps the heading pot value to the heading display
  setHeading(potHead);                        // Displays the heading information on the display
  delay(10);
}

void setHeading(int potHead) // Build the setHeading Function
{
  int cR;
  cR = potHead/24;
  
  lcd.createChar(0, headA); // Defines Heading Arrow
  lcd.createChar(1, headN); // Defines North Marker
  lcd.createChar(2, headS); // Defines South Marker
  lcd.createChar(3, headE); // Defines East Marker
  lcd.createChar(4, headW); // Defines West Marker

  lcd.setCursor(9, 1);
  lcd.print(potHead);  // Displays Heading in Degrese
  lcd.setCursor(10, 2);

  lcd.write(0);  // Heading Indicator

  lcd.setCursor(cR, 3);
  lcd.write(2); // South
  lcd.print("....");
  lcd.write(4); // West
  lcd.print("....");
  lcd.write(1);  // North
  lcd.print("....");
  lcd.write(3); // East
  lcd.print("....");
  Serial.println(potHead); // Used for Serial Debugging
}

I hope this clears up my goal, and my problem. And Helps someone else along the way.

I'm using a 1 k ohm resistor at both ends of the pot. but I guess you method is ok.
I only have a 2 line display so I have to omit 2 lines or try multiplexing.
Right now my setup is not wrapping around.
You might try googling "lcd wrap-around-text code"
check out this post :
http://forums.parallax.com/showthread.php/138548-LCD-text-wrapping-and-looking-at-previous-text-cut-off

I looked at your code. I'm using the Map function as well but I'm mapping the pot to 360 degrees, not 720 degrees like you.
360-(-360)=720
Your mapping statement maps the pot to 720 degrees. How is that supposed to work ?
You can do this any way you want but if I were you , asking for help, I would provide quite a bit more
information, specifically a table of values that correlates the "CR" variable that functions as the cursor position setting.
You need to use:

Serial.print("CR = ");
Serial.println(CR);

and photograph the display before and after the line change or find some other way to correlate the CR value to what
is happening on the display in order for anyone to be able to help you. I think it has something to do with addressing
but at this point it could be anything. You haven't provided much in the way of "observations".
You need to be able to state:
When CR changes from [XX] to [YY] , line ["B"]changes to line ["A"] , or something to that effect.
You are working with numerical values. Your problem is related to the change in those values and you are asking
for help and providing essentially no data. Obviously an experienced programmer could write the program without
any input from you other than what you put in your original post, but until that happens, everything is troubleshooting,
and that is by nature a trial and error method. You try something, record the results, and try something else etc...
Yes, anyone else can run your code and collect all the data but quite honestly I think you should be collecting the data
and posting it so someone can look at it and say "Oh yeah, of course, your problem is this...."
Provide a table of values collected using serial print statements that correlates the value of CR to the line changes.
You might also explain how you go from -360 degrees to 360 using a display an equation designed for a 360 degree
compass . I'm just not getting that. Maybe you could explain that
Have a look at this post:
http://forum.arduino.cc/index.php/topic,14140.0.html
It looks like the display is mapped "as if" all the lines were layed out end to end and you actually have more than
one cursor position variable, actually one for each line so if you have 4 lines times 20 characters then your line-1
cursor position variable would be 0 to 19,
line 2: 20 to 39,
line 3: 40 to 59,
line 4 60 to 79.
Can you try these values to see what happens ? (I don't have a 4 line display)

This is how my pot is setup..

arduino_rotator_controller.bmp (607 KB)

Have a look at this post:
http://forum.arduino.cc/index.php/topic,14140.0.html
It looks like the display is mapped "as if" all the lines were layed out end to end and you actually have more than
one cursor position variable, actually one for each line so if you have 4 lines times 20 characters then your line-1
cursor position variable would be 0 to 19,
line 2: 20 to 39,
line 3: 40 to 59,
line 4 60 to 79.
Can you try these values to see what happens ? (I don't have a 4 line display)

If you look at the post that you mentioned you will find that in reply #3 I referred to the same LCD Addressing link that I pointed out earlier in this thread.

If you look at the explanation of the 20x4 memory map at that link, and if you convert your decimal addresses to hex, you will see that your addressing theory is incorrect. There is no need to 'see what happens' since we already know how the controller works.

If you insist on using decimal addresses, which is really a poor idea since all of the documentation uses hex, the values would be:
line 1: 0 to 19
line 2: 64 to 83
line 3: 20 to 39
line 4: 84 to 103

Don

Thanks for correcting that for me Don.

Got it.
Your using 3.3V for the pot.
I'll change my setup to match yours.
I'll see if I can reproduce the symptom using a 2 line display.
What about the 720 degrees ?
How do you explain that ?

I know your maximum value from the pot is 686 , which is close to 720, but if you map 686 to
720 you are creating a new range that has no corresponding values in the original range.
If you started with 720 and mapped it down to 686 then you could say some of the values
in the original range will have to be shared in the target range so pot movement will have
no effect in the shared values. By going from a smaller range to a larger range , that means
there are compass headings that have no corresponding values in the pot range .
Is this not correct ? Please explain. I don't get it.
Why did you change the setHeading function ?
BEFORE

  void setHeading(int x)
{
  int Heading;
  int CR;
  
  Heading = x/1.388;
  CR = x/25;
  
  lcd.createChar(0, headA); // Defines Heading Arrow
  lcd.createChar(1, headN); // Defines North Marker
  lcd.createChar(2, headS); // Defines South Marker
  lcd.createChar(3, headE); // Defines East Marker
  lcd.createChar(4, headW); // Defines West Marker

  lcd.setCursor(9, 1);
  lcd.print(Heading);  // Displays Heading in Degrese
  lcd.setCursor(10, 2);

  lcd.write(0);  // Heading Indicator

  lcd.setCursor(CR, 3);
  lcd.write(2); // South
  lcd.print("....");
  lcd.write(4); // West
  lcd.print("....");
  lcd.write(1);  // North
  lcd.print("....");
  lcd.write(3); // East
  lcd.print("....");
}

NOW

  void setHeading(int potHead) // Build the setHeading Function
{
  int cR;
  cR = potHead/24;
  
  lcd.createChar(0, headA); // Defines Heading Arrow
  lcd.createChar(1, headN); // Defines North Marker
  lcd.createChar(2, headS); // Defines South Marker
  lcd.createChar(3, headE); // Defines East Marker
  lcd.createChar(4, headW); // Defines West Marker

  lcd.setCursor(9, 1);
  lcd.print(potHead);  // Displays Heading in Degrese
  lcd.setCursor(10, 2);

  lcd.write(0);  // Heading Indicator

  lcd.setCursor(cR, 3);
  lcd.write(2); // South
  lcd.print("....");
  lcd.write(4); // West
  lcd.print("....");
  lcd.write(1);  // North
  lcd.print("....");
  lcd.write(3); // East
  lcd.print("....");
  Serial.println(potHead); // Used for Serial Debugging
}

VA3WPN,
Have a look at the link Don gave you.
I think your time would be better used understanding what is on that page.
see the image of your memory map I copied.
Maybe you should think about creating a hex array to match that memory map.
I don't know. I know the cursorset arguments are decimal, not hex but I think
the attached image explains the symptom you have been describing.

LCD-20x4-memory(b).gif

Maybe you should think about creating a hex array to match that memory map.

That seems to be the solution that was most favored in previous discussions of similar problems.

Don