NerdKits - electronics education for a digital generation

You are not logged in. [log in]

NEW: Learning electronics? Ask your questions on the new Electronics Questions & Answers site hosted by CircuitLab.

Microcontroller Programming » Led Marquee question

April 09, 2009
by mcai8sh4
mcai8sh4's Avatar

I've made the LED Marquee, and all works well. The problem I'm having is with the python listener program. (I know it's in python and not C, but there isn't a python programming section) Whilst it all works, I'd like to alter it, whilst I've used c before (although I am very rusty), I've never played with python - and I'm struggling. I'm not sure if this is possible - but this is what I'm trying to do either 1) alter the original program to display the arguments then end (ie py-marquee "Thanks to Nerdkits") or 2) alter the original program so that stuff (text, script output) can be piped to program then displayed : ie echo "Hello" | py-marquee

It may just be me, but the netcat method is tricky to include in simple bash scripts.

I've tried altering the program, but every time I break it and have to start again. Option 2) would be preferable (or are option 1) and 2) the same?). Would this even be possible does it not work like that?

Any help would be appreciated.

Thanks

April 09, 2009
by mcai8sh4
mcai8sh4's Avatar

hmm, sorry about the formatting - it looked better when I typed it... honest.

April 09, 2009
by Soybean
Soybean's Avatar

Well, I haven't made a LED Marquee, but I know a bit of Python.

It sounds like your problem is just a matter of syntax, is that correct? That is, as I understand it, you'd like everything to keep working the way it currently does, except that instead of typing echo "HI MOM!!!" | netcat localhost 6666 to make it happen, you'd like to type either py-marquee "HI MOM!!" or echo "HI MOM!!" | py-marquee

If my understanding is correct, I don't think you actually want to modify the existing python script. It's doing a surprising amount of work for such a tiny script -- it displays the time when it's not displaying another message, and it listens for new messages on a network port. In fact, you should be able to send messages to it from another computer, which seems pretty awesome to me.

What I would do (again, if I'm understanding you correctly), is create another script or program that interacts with the existing one. This new script/program could be written in whatever programming language you're most comfortable with. It could either use a socket library to write a message to the appropriate socket, or it could just be a wrapper that calls "netcat localhost 6666".

April 09, 2009
by Soybean
Soybean's Avatar

Ugh, I see what you mean about the format mangling. A preview button would be handy here.

April 09, 2009
by mcai8sh4
mcai8sh4's Avatar

@Soybean - thanks for the input. My plan was to alter the program on the chip (to just show something every now and again when it's not being used), then have another program to display things like I mentioned. The current python script does display the time (nice touch I agree - but not needed for my intentions), and listens for text to display. You're correct, this is a nice little script.

The problem I have is (say I'm incorporating this into a bash script or something) if I have some results that I want to display on my marquee, then when I netcat it across, I'm then stuck in netcat until there is some interaction from myself.

That is why I want to just pipe stuff out to the marquee. I've tried removing all the socket stuff from the script and just pulling parameters (although not really sure what I'm doing with that), and then storing the text to a var to send it through when the marquee asks for the next char. I've been trying (on and off admittedly) for a couple of weeks, but to no avail.

Long story short - a stand alone script (doesn't have to be in python) that I can just pipe data to to display it. Since the python-listener.py already contains the correct code to send stuff to the marquee, I thought I could use that as the base and just remove the socket stuff, but I can't seem to get it to work.

Thanks again for the help

April 09, 2009
by Soybean
Soybean's Avatar

Ah, ok, I misunderstood.

Well, I'm a little out of my depth here, and I don't even have pySerial intalled here at work, let alone an LED marquee to test things on. But I can give it a shot until someone more competent comes along. It seems to me like the following should be all that's required:

<code>

 import serial

 serial = serial.Serial("/dev/ttyUSB0", 115200)
 mystring = "TEST STRING\n"

 serial.write('b')
 for data in mystring:
      if not data == '\n':
           serial.write(data)
           response = serial.read()
           if not response == 'n':
                print "Received: " + response
                #This is a debug line, since I'm a bit fuzzy on some details
                break
 serial.write('a')

</code>

Of course, this always sends the same string, but if this works, it should be pretty trivial to get it to send whatever string you want. For the "piping input" method, you'd just add "import sys" at the beginning, and replace "mystring = "TEST STRINGn"" with "mystring = sys.stdin.readline()".

If this doesn't work, you can tell me what goes wrong with it, and I can keep trying... or you can just wait for someone who actually knows what they're talking about, or who at least has suitable tools available. ;)

April 09, 2009
by mcai8sh4
mcai8sh4's Avatar

Thanks, that looks nothing like what I was creating! I've been telling myself for years to learn python, but never got round to it.

I'll wire up the NerdKit, and try this out. Even if it doesn't work, it will be easier for me to understand as there's less lines to worry about.

Thanks once again, much appreciated.

April 09, 2009
by mcai8sh4
mcai8sh4's Avatar

Thats NerdKit-eriffic!! Works well, thank you very much. I had to add #!/usr/bin/python to the beginning (I am very new to python), but after that perfect.

I now just have to edit it like you said, and I'm back in the game. The only other thing, which I doubt you can help with (although I'm now in a position to play around and figure it out), there's a scroll display (what your prog does) and a static display, I just need to work out how to switch between the two.

Thanks for your time on this, I'm off to play around, see if I can figure out what you did.

:D

April 09, 2009
by Soybean
Soybean's Avatar

Oh, I'm glad it worked! Figuring that out was a lot more fun than what I should have been doing at work this afternoon.

Suprisingly, I do have a vague idea about how the scroll/static thing works. The line "serial.write('b')" is switching to scrolling mode, and "serial.write('a')" switches back to static. I switched between them because that's what the sample code does (switching between a scrolling message and a static time display), and I couldn't think of any other way to make sure it was in the correct state without possibly having weird things happen.

So for a static display, I'd start with "serial.write('a')". It looks like that should always work to get you into static mode. Then, right under that (before the for loop) add the line "serial.write('z')", which clears the display in static mode. Finally, take out the "if not data == 'n':" line (and reposition everything appropriately). It looks like the static display mode waits for a 'n' or 'r' before printing anything.

April 09, 2009
by mcai8sh4
mcai8sh4's Avatar

I thought something like that, I'll have to play around, see what I can do. It's starting to make a little more sense to me now.

Thanks again for your time.

April 09, 2009
by hevans
(NerdKits Staff)

hevans's Avatar

I was going to post here and try to explain our use of 'a', and 'b' to switch between scrolling and static mode, but it looks like you guys have managed to figure it out, so instead I'll try to explain why we made a couple of the design decisions that seem to have added some confusion to the project.

We chose to have these two scrolling modes, because we wanted to display the current time while nothing needed to be scrolled across the display. This feature also led us to use the socket idea to send a new message. In our design the LED Marquee is more like a process that is always running on your computer sending the time (or other static message) to the Marquee, this process is also sitting and listening on a socket for other programs to be able to send it text to scroll across the screen. With our design it is very easy to modify other, already running programs on your computer to send data out to your Marquee, just a few lines that open a socket and send the data through. To be honest for this project the thing we were most interested in was driving lots of LEDs with a single NerdKit, and admittedly the software around it was a bit of an afterthought. That said, it is possible to substantially simplify the code by removing the static mode and having only a scrolling mode, and by just piping individual message through to the serial port using python like Soybean posted.

I'm glad you all have been able to figure it out, and there is now this forum where the community can pick up the slack on things we don't explain very well =P.

April 10, 2009
by mcai8sh4
mcai8sh4's Avatar

OK, all's working good, and I'm things are starting to make sense. As a second script I have

#!/usr/bin/python
import serial
import sys
import time
serial = serial.Serial("/dev/ttyUSB0", 115200)
mystring = sys.stdin.readline()
serial.write('a')
serial.write('z')
serial.write(mystring)
time.sleep(5)
serial.write('z')

Whilst it displays my test nicely, I expected it to clear the display after 5 seconds, but it doesn't (this is just for testing purposes), the text stays on the display until the battery dies.

Anyway, I'm sure I can sort that out somehow, I'm reading lots of pages about python, so it should all come good eventually.

Once I've got all the functionality I want from the two programs I was wondering if it would be possible (or not... or even too difficult for someone with my level of knowledge) to combine the two and then use something along the lines of :

echo "HELLO" | py-marquee --scroll
echo "HELLO" | py-marquee --static

or similar, that is to use the same program to so both.... I realise that by the end of this I'll probably arrive at the same program I started with (python-listener.py), but at least I'll have learn't something.

April 10, 2009
by hevans
(NerdKits Staff)

hevans's Avatar

The reason as to why your marquee isn't clearing when you tell it to is inside ledarray2.c

If you take a look at the static display part you find this loop:

while(1) {
    // fill buffer
    x = uart_read();

    if(x=='a') {
      // ignore
    } else if(x=='b') {
      // change modes
      ledarray_blank();
      return;
    } else if(x=='\r' || x=='\n') {
      // render
      for(i=0; i<bufpos; i++) {
        if(buf[i]=='z') {
          ledarray_blank();
          offset = 0;
        } else {
          font_display(buf[i], offset); offset += font_width(buf[i])+1;
        }
      }
      // clear buffer for next line
      bufpos = 0;
    } else {  
      // add to buffer
      buf[bufpos] = x;
      if(bufpos < 16-1) bufpos++;
    }    
  }

the call to x = uart_read() is only going to read one character into x that is waiting on the serial port. This look is going to execute over and over, putting one character at a time into the buffer until it encounters either a 'b', which will switch to scrolling mode, or a 'n' which tells the code that that string is done, and then it renders to the actual LEDs. The call to clear the buffer if there is a 'z' is inside this condition, so your buffer won't actually be cleared (and the empty buffer rendered to the screen) until you send the 'n'. Note that when you take input from stdin.readline() like you did in your script, that line waits until you press enter so your mystring string is always terminated with a 'n' So adding a

serial.write('\n')

to the end of your python program should clear your marquee for you.

About your second question. It is easy in python pass arguments to your script. Just import the sys module with

import sys

sys.argv is a list that contains the name of your script as the 0th value, followed by the rest of the arguments given. So you could do.

myArg1 = sys.argv[1]

Then do some ifs to do the scroll or the static.

Hope this helps.

Humberto

April 11, 2009
by mcai8sh4
mcai8sh4's Avatar

Ahh, thanks for the explanation, makes sense to me now. I had a play with the code you mentioned to try and figure out exactly what was happening, but I messed up and broke it. So I put it back to how it was then left it alone.

Your explanation saves me from messing everything up again. I'll have a play with that and the sys module.

Thanks

Post a Reply

Please log in to post a reply.

Did you know that you can turn a $20 digital scale into a live weight sensor using our kit with a few extra parts? Learn more...