AaronLiddiment / RGBLEDS

Matrix, Text & Sprite libraries for use with FastLED
68 stars 28 forks source link

QUESTION: How to display variable text? #4

Closed Delphi closed 9 years ago

Delphi commented 9 years ago

Hello, first I would like to thank you for creating a great library.

I am fairly new to Ardunio programming with about 6 months experience, so chances are I do not understand C/C++ well enough yet.

I am attempting to display a variable message that would scroll a score and name for a scoreboard I am creating using WS2801 strips, I will soon have some WS2811 strips also.

If I use the following static line of code my message displays just fine:- char ScoreTxt[] = { EFFECT_SCROLL_LEFT EFFECT_HSV_CH "\xff\xff\xff\x40\xff\xff" " wibble " };

Using Serial.print(ScoreTxt[i], HEX); The hex output for this working char array is:- FFFFFF90 FFFFFFCB FFFFFFFF FFFFFFFF FFFFFFFF 40 FFFFFFFF FFFFFFFF 20 77 69 62 62 6C 65 20 0 Using sizeof(ScoreTxt) it reports that I have 17 chars.

When I try to use a variable to replace my static message I start to run into some complications adding the variable string into the char array, I suspect this to partly be down to the hex control codes being handled incorrectly.

I have used the following method to generate my string and then convert it to a char array:- char col[] = { "\xff\xff\xff\x40\xff\xff" } ; String varcol = String(col[0]) + col[1] + col[2] + col[3] + col[4] + col[5]; String txt = " wibble "; String str = EFFECT_SCROLL_LEFT EFFECT_HSV_CH + varcol + txt; int len = str.length()+1; char msg[len]; str.toCharArray(msg, len);

Using Serial.print(msg[i], HEX); The hex output for this non-working char array is:- FFFFFF90 FFFFFFCB FFFFFFFF FFFFFFFF FFFFFFFF 40 FFFFFFFF FFFFFFFF 20 77 69 62 62 6C 65 20 0 Using sizeof(msg) it reports that I have 17 chars.

I then send the char array for display using:- ScrollingMsg.SetText((unsigned char )ScoreTxt, sizeof(ScoreTxt) -1); OR ScrollingMsg.SetText((unsigned char )msg, sizeof(msg) -1);

Comparing the 2 char arrays ScoreTxt and msg appear to have the same number of chars in the array and each array item has the same corresponding hex value, unfortunately the message is not displayed correctly via the LED's.

ScoreTxt displays exactly as one would expect it to. msg seems to attempt to display something however the board mainly sits black with the odd LEDs blinking on then off as if the message is corrupted.

If I use the following to create my message:- ScrollingMsg.SetScrollDirection(SCROLL_LEFT); ScrollingMsg.SetTextColrOptions(COLR_HSV, 0x00, 0xff, 0xff, 0x40, 0xff, 0xff); char txtmsg[] = { " message goes here " }; ScrollingMsg.SetText((unsigned char *)txtmsg, sizeof(txtmsg) - 1);

The message does seem to appear although does not seem to follow the colour codes, I also notice some stray pixels at the end of the message, sometimes a '?' is displayed which jumps about the display.

Having got to this point I am now struggling to get this working with variable messages, where the intention is to have the Arduino Mega2560 receive a score and name via serial from another Arduino, however I am taking baby steps by trying to use a variable first.

If anyone can shed any light on what I may be doing wrong, or advise how I can send a variable text message for display it would be highly appreciated.

Many thanks for taking the time to read.

Regards Delphi

AaronLiddiment commented 9 years ago

Hi, The first thing I would say is that you should always use 'unsigned char' or 'unit8_t' for the array passed to SetText(), this is important for any control codes that may be incorporated into the text. I would imagine that 'String' only expects chars and may well be having trouble with the control codes, I have never used string so cannot be of more help with this at the moment. Have you come across the sprintf() command? You could try this...... unsigned char txtmsg[40]; char name[20]; int score; strcpy(name, "Jimmy"); score = 1234; sprintf((char *)txtmsg, "%s your score is %05d", name, score); ScrollingMsg.SetScrollDirection(SCROLL_LEFT); ScrollingMsg.SetTextColrOptions(COLR_HSV | COLR_GRAD_CH, 0x00, 0xff, 0xff, 0x40, 0xff, 0xff); ScrollingMsg.SetText(txtmsg, sizeof(txtmsg) -1);

I am out of time for now, will check back later and see how you get on. You could also build the string using strcpy() or memcpy() into an unsigned char array.

Regards Aaron

Delphi commented 9 years ago

Hello Aaron,

Thank you for the quick response, I have tried what you have suggested above and have yielded some mixed results, the score it would seem messes with the end of the sequence with it often displaying 01234t t t 5 with the T and 5 jumping about the display, even tho there is no 0,5 or t in the int. The rest of the message before it seems to display well.

I will continue to research more into the use of the various functions you mentioned to get a greater understanding. Thanks for the example code as this has got me closer :)

Ill let you know how I get on.

Regards Delph

AaronLiddiment commented 9 years ago

Hi, Very strange, it would seem that the length of the message is being set incorrectly... What board are you using and what version of the Arduino program are you using? Regards Aaron

Delphi commented 9 years ago

Hi, I am using a Arduino MEGA2560, purchased from - http://www.maplin.co.uk/p/arduino-mega-2560-r3-development-board-n31ku.

I was running IDE 1.0.6, but I have just checked and downloaded the latest v1.6.4. Using v1.6.4 seems to compile quicker, bust sadly made no difference to the led display.

In IDE I have selected:- Board = "Ardunio Mega or Mega 2560" Proc = Atmega2560 Programmer = Arduino as ISP

Pre defined static messages display without issue, it is just those that are generated on the fly that have issues.

Here is a copy of the sketch.,,

include

include

include

include

// Change the next 6 defines to match your matrix type and size

define NUM_LEDS 90 //9 // How many leds in the strip?

define DATA_PIN 51 // set the RGB LED data pin

define CLOCK_PIN 50 // set the RGB LED clock pin

define BRIGHTNESS 25

define COLOR_ORDER RGB

define CHIPSET WS2801

define MATRIX_WIDTH 13

define MATRIX_HEIGHT -7

define MATRIX_TYPE HORIZONTAL_ZIGZAG_MATRIX

int TripTime = 5000; int OriginX = 0; int OriginY = 0;

cLEDMatrix<MATRIX_WIDTH, MATRIX_HEIGHT, MATRIX_TYPE> leds; cLEDText ScrollingMsg;

void setup() { FastLED.addLeds<CHIPSET, DATA_PIN, CLOCK_PIN>(leds[0], leds.Size()); FastLED.setBrightness(BRIGHTNESS); FastLED.clear(true); ScrollingMsg.SetFont(MatriseFontData); ScrollingMsg.Init(&leds, leds.Width(), ScrollingMsg.FontHeight() + 1, OriginX, OriginY); Serial.begin(19200); }

char ScoreTxt[] = { EFFECT_SCROLL_LEFT EFFECT_HSV_CH "\xff\xff\xff\x40\xff\xff" " OTTER OTTER OTTER " };

char other[] = { EFFECT_HSV_AV "\x00\xff\xff\x40\xff\xff" " || OTTER OTTER OTTER " EFFECT_HSV_CV "\x00\xff\xff\x40\xff\xff" " ||| OTTER OTTER OTTER " EFFECT_HSV_AH "\x00\xff\xff\xff\xff\xff" " |||| OTTER OTTER OTTER " EFFECT_HSV_AV"\x00\xff\xff\x40\xff\xff" " 0123456789 ABCDEFGHIJKLMNOPQRSTUVWXYZ !\"-+=#@:;.,?>< " EFFECT_HSV_AH "\x00\xff\xff\xff\xff\xff" " abcdefghijklmnopqrstuvwxyz " };

void loop() { if (ScrollingMsg.UpdateText() == -1) { unsigned char msg[40]; char name[20]; int score; strcpy(name, "Jimmy"); score = 1234; sprintf((char )msg, "%s your score is %05d", name, score); ScrollingMsg.SetScrollDirection(SCROLL_LEFT); ScrollingMsg.SetTextColrOptions(COLR_HSV | COLR_GRAD_CH, 0xff, 0xff, 0xff, 0x40, 0xff, 0xff); ScrollingMsg.SetText((unsigned char )msg, sizeof(msg)); for(int i = 0; i < sizeof(msg); i++) { Serial.print(msg[i], HEX); Serial.print(" "); } Serial.println(" -.msg "); } else { FastLED.show(); } delay(50); }

Note, that although I have set #define MATRIX_HEIGHT -7 as I wired up my strip from top down, ie:- 123 654 789

Switching this to 7 instead of -7 has no effect in terms of the display output, only its rotated/flipped 180,

Thanks for helping out.

Regards Delph

AaronLiddiment commented 9 years ago

Hi,

Sorry, not paying attention, you had already mentioned the board ;)

Think I know your problem, you are declaring your unsigned char array within a function, which means it is declared on the stack and will loose its contents when you exit the function! Move your unsigned char array declaration to outside of the function so that it is global and your problem will go away. This should also work with your original code :)

Best regards Aaron

AaronLiddiment commented 9 years ago

Hi again, Of course if you prefer you could still declare it in the function but could add the 'static' keyword before the type , eg static unsigned char msg[40]; Regards Aaron

Delphi commented 9 years ago

Hello Aaron, Thank you for the tips. I found that using a dynamically changing sized char array caused some issues, so instead I have broken the message down into manageable static sized chunks to which I measure the length and if shorter than the static char array size then pad out the string with 'space'.

Using "static" seemed to help, so thank you.

Here is a copy of my code which generates a random number to be displayed 10x then a scrolling message, repeat.

include

include

include

include

// Change the next 6 defines to match your matrix type and size

define NUM_LEDS 90 //9 // How many leds in the strip?

define DATA_PIN 51 // set the RGB LED data pin

define CLOCK_PIN 50 // set the RGB LED clock pin

define BRIGHTNESS 100

define COLOR_ORDER RGB

define CHIPSET WS2801

define MATRIX_WIDTH 13

define MATRIX_HEIGHT -7

define MATRIX_TYPE HORIZONTAL_ZIGZAG_MATRIX

int TripTime = 5000; int OriginX = 0; int OriginY = 0; cLEDMatrix<MATRIX_WIDTH, MATRIX_HEIGHT, MATRIX_TYPE> leds; cLEDText ScrollingMsg;

void setup() { FastLED.addLeds<CHIPSET, DATA_PIN, CLOCK_PIN>(leds[0], leds.Size()); FastLED.setBrightness(BRIGHTNESS); FastLED.clear(true); ScrollingMsg.SetFont(MatriseFontData); ScrollingMsg.Init(&leds, leds.Width(), ScrollingMsg.FontHeight() + 1, OriginX, OriginY); Serial.begin(19200); }

static unsigned char Txt[] = { EFFECT_SCROLL_LEFT EFFECT_HSV_CH "\xff\xff\xff\x40\xff\xff" " OTTER OTTER OTTER " };

void loop() {
if (ScrollingMsg.UpdateText() == -1) { for(int i = 0; i < 10; i++) { RandomScoreTime(); delay(1000); FastLED.showColor(CRGB::Black); FastLED.show(); } ScrollingMsg.SetScrollDirection(SCROLL_LEFT); ScrollingMsg.SetTextColrOptions(COLR_HSV | COLR_GRAD_CH, 0xff, 0xff, 0xff, 0x40, 0xff, 0xff); ScrollingMsg.SetText(Txt, sizeof(Txt) -1); } else { FastLED.show(); delay(50); }
}

void RandomScoreTime() { String str = String(random(99)); str += " "; static unsigned char msg[3]; str.toCharArray((char *)msg, 3); RandomColour(random(5)); ScrollingMsg.SetText(msg, sizeof(3)); FastLED.show();
ScrollingMsg.UpdateText(); }

void RandomColour(int col) { if (col == 1) { ScrollingMsg.SetTextColrOptions(COLR_HSV | COLR_GRAD_AH, 0xff, 0xff, 0xff, 0x40, 0xff, 0xff); } if (col == 2) { ScrollingMsg.SetTextColrOptions(COLR_HSV | COLR_GRAD_AV, 0x60, 0x40, 0x70, 0x60, 0xff, 0xff); } if (col == 3) { ScrollingMsg.SetTextColrOptions(COLR_HSV | COLR_GRAD_CH, 0xff, 0xff, 0xff, 0x40, 0xff, 0xff); } if (col == 4) { ScrollingMsg.SetTextColrOptions(COLR_HSV | COLR_GRAD_CH, 0x88, 0xff, 0xff, 0x20, 0xff, 0xff); } if (col == 5) { ScrollingMsg.SetTextColrOptions(COLR_HSV | COLR_GRAD_CV, 0xff, 0xff, 0xff, 0x40, 0xff, 0xff); } if (col == 0) { ScrollingMsg.SetTextColrOptions(COLR_RGB | COLR_GRAD_CH, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00); } }

Once again, thanks for your help.

Regards Delphi

bikemule commented 9 years ago

First, thanks! This library is amazing!

Sadly, I am having a similar issue using an RFduino chipset, Arduino 1.6.5, and a very recent (master branch from a few weeks ago) FastLED 3.1. I was thinking it was an issue with the newer version of FastLED until I saw this.

To be specific, I am having the issue where the string doesn't get erased past where I updated it. I even added a null byte after the string I copied and then tried memcopying null bytes throughout the whole array before I copied it in.

I then thought using strlen instead of sizeof would solve the problem, but using strlen (on an unsigned char *, as per your suggestion) gives an invalid conversion error.

AaronLiddiment commented 9 years ago

Hi, If I understand you correctly, the problem you are having is when you change the contents of the char array to a message with less characters in it, the characters from the longer message are being left behind. This happens because the code stops rendering letters when it gets to the end of the array even when the BACKGROUND_ERASE option is active. The way around this is to do a FastLED.clear(); just before your UpdateText() call. Alternatively you could always make the array the same length by filling the unused area with blank spaces rather than null's. Regards Aaron