PDA

View Full Version : Retrieving and storing serial string data to an array



jdshoe
01-16-2012, 01:54 PM
Hello,
I'm working on a small project where I'm interfacing with the uMP3 player. I would like to issue a serial command ("FC L") and receive a directory listing into an array. The data (filenames) received should be separated by {CR}. I'm having trouble getting past this. I would really appreciate if anyone has sample SPIN code to perform this type of function.

The uMP3 datasheet can be found here (http://www.roguerobotics.com/files/ump3/documentation/UMP3-110-A1-102.pdf)

Thanks in advance!

-Justin

T Chap
01-16-2012, 02:12 PM
Welcome to the forum Justin.

First, have you already been trying to get it to work and have some code? If so, please post what you have done so far. Next, is there a maximum number of file names or could it be that the file names could be grow and you can't determine the number? The reason is that if you want to store the file names into an array, you will have to consider that at some point there may not be enough memory to temporarily hold all the names at once. If that is the case, you would need to determine what is the purpose of having the list held at once, and if it can be that you could read in some amount of names based on array size, do something with that info, then read more. Are the file names in an 8.3 format or can they exceed that size? (12345678.123)

There are several serial objects that will make sending the get list command and then reading the data back with the CR delimiter, that part is very east. I am sure that others will have good suggestions on this as well. But first things first, can you explain what the goal of the list is, and then someone can best show an example of how to manage the data. Can the uMP3 allow getting a partial list, pause, then continue where it left off reading?

jdshoe
01-16-2012, 02:29 PM
Hi TChap. Thanks for the quick response. I'm building an alarm clock that will play mp3 files at wake up. Knowing I could run into a memory problem storing a large list, I was planning on just assuming a limitation of reading 12 files, regardless of how many are on the SD card. I wanted to store them into an array to allow random playback, or song skipping. My other assumption is all files will be in 8.3 format. Unfortuantely, I don't have any useful code at this point. I've tried using some snippits from (http://forums.parallax.com/showthread.php?102739-Trying-to-receive-a-long-STRING-via-ExtendedFDSerial.SPIN) but didn't come close to the results I was hoping for. At the most basic level, I'm just looking for code that will receive serial strings separated by CR, up to 10, and store in an array. Thanks for your help!

T Chap
01-16-2012, 02:39 PM
OK. Just as a side note, if you did want to store a larger list to have more options to randomly select from, you could save the list in an extra eeprom or ram. But for now, you should focus on getting some basic communication going to learn from. Have you already looked at this object for the uMP3? It has an example that looks straight forward. I assume you have configured the device for the correct communication(serial).

http://obex.parallax.com/objects/156/

I have never used the uMP3, probably others here have and will have more input.

Franklin
01-16-2012, 08:26 PM
One way to have more names is to format the name on the fly and name your files on the sd card with that format. If you call your files "file01.mp3", " file02.mp3" you only need to generate the number randomly and concatenate the file name on the fly.

jdshoe
01-16-2012, 11:07 PM
Hi T Chap,
I am using that object for other commands, but it doesn't have a file listing command. Are there any serial communication objects that will store the received data in an array (using CR as a delimiter)?

Thanks!

Duane Degn
01-16-2012, 11:15 PM
Justin,

I'm not sure what you mean by "received data". Is this data you're typing in? Could you have your list of songs hard coded into the program in the DAT section?

T Chap
01-17-2012, 12:44 AM
I just threw something together to get you going. This does not parse the data, it just reads in the first 64 bytes of the response. Parsing will be more involved, but first see if you can at least get something that looks like a legit response. Hopefully others will have some advice on this, and/or corrections on what I posted. Using the LCD will require some tweaking to be useful as the only means of display. The parallax serial terminal may be easier to see all the content but this will get you started.

Resave the uMP3 object after adding this so the main program can use the new method.

Add this method to the main program as the first method ( uMP3 test )




VAR
byte listarray[64] 'add this to main prog var section

PUB GetFileList | ii
ii := 0
if lcd.start(0, 19_200, 4) ' 4x20 Parallax LCD on A0, set to 19.2k
lcd.cursor(0) ' no cursor
lcd.cls ' clear LCD scrren
lcd.backlight(1) ' backlight on
lcd.str(string("Dir List Test")) ' display header
if uMP3.start(RxPin,TxPin,9600) ' start uMP3 (Rx,Tx,Baud)
uMP3.wait ' wait for idle
if uMP3.idle ' check that uMP3 is stopped
uMP3.GetDir(@listarray)
lcd.cursor(0)
repeat 32 'display first 32 bytes on LCD (2x16 display)
lcd.str(@listarray + ii)
ii++
waitcnt(160_000_000 + cnt) 'allow time to view first 32
repeat 32 'display next 32 bytes on LCD (2x16 display)
lcd.str(@listarray + ii)
ii++
else
lcd.cls
lcd.str(string("uMP3 failed to start.")) ' if uMP3 doesn't start, report error


Add to uMP3 obj and save it.


PUB GetDir(listptr) | i
'' Returns uMP3 file listing
i := 1
if started
Serial.RxFlush ' flush any old receive stuff
Serial.str(String("FC L",13)) ' uMP3 get list
listptr := Serial.RxTime(1000) ' wait here for 1 second for first byte of reply
Repeat 63 'adjust this to suit your needs, change array length declared in main program
listptr[i] := Serial.RxTime(2) 'get the rest of the reply.
if listptr[i] == -1
return 3 ' return any value to show that no data was received or the end was reached. debug purposes only
i++

jdshoe
01-17-2012, 05:05 AM
Thanks Everyone!

Duane,
I would like to receive the list from the SD Card connected to the uMP3 device. I could store the list with predetermined song names, but that is my backup plan if I cannot retrieve a dynamic file list from uMP3.

T Chap,
Thanks for writing this test code. I appreciate your time looking at this. I have tried the test code and the output so far is unreadable. I will keep working on it. I have tried reading different directories, just the root, and changing filename lengths, and number of files. It looks like it may also be due to limitations in "Serial.RxStrTime". I'll look more tomorrow and let you know. Thanks for the help!

-Justin

T Chap
01-17-2012, 05:08 AM
Justin, in an earlier version I had used rxstrtime, but notice in the newer version it is rxtime. What are you seeing on the LCD?

jdshoe
01-17-2012, 02:10 PM
I'm getting 00000 as a result when I list a directory with 3 files in it. Test1.mp3, Test2.mp3, Test3.mp3.
The uMP3 object uses Extended_FDSerial. That has RxStrTime (ms,stringptr) : Value | ptr, temp and RxTime(ms).

The RxTime method only has one parameter, which is why I modified your code above to use RxStrTime. The uMP3 player manual also states it first returns a space character, then starts transmitting the file list with CR delimiters.

So I guess I have 2 questions.
If I use RxTime, how should I rewrite the code for only one parameter? Or should I use RxStrTime...
Is the space character causing me an issue?

I really appreciate your time T Chap. I have a bit of a learning curve, so I understand if you cannot help further. I can test with a static file naming system if I cannot get a dynamic list. Retrieving the listing was my preferred method.

Thanks!

-Justin

T Chap
01-17-2012, 03:14 PM
That is my mistake, I tried to just quickly modify that object and made a mistake. See the corrected code above. I can work on this a little later today, but see if that produces a response other than 0.

What you want to accomplish is easy, just takes a little time to sort it out, and there is a learning curve which is very rewarding. Plenty of the other guys on here could write something in a few minutes to solve your concept and it would be slick right away, but I have to spend time trying to figure things out as I go(referred to as a 'hack'). Most people on the forums know that it is best for the new guys to dive in, try some things, post what they have, and hash it out part by part, which enhances the learning process. I would recommend that you see what results you get from the above, post the results. But also post your methods and/or spin files here, plenty of the more experienced guys here will then have much faster and more frequent input if they can see the code 'at a glance'.

Side note: The code I posted does not parse out any characters, it is simply to attempt to get a response and show anything that resembles a file name. It may be a good idea to go ahead and incorporate the PST(parallax serial terminal) as an extra display for debug purposes, so you can see the responses on the PC. It is the same exact method of serial.str(xxxxxxxx) except you are replacing the LCD with the PST object ie pst.str(xxxxxx).


Did you get the uMP3.status or uMP3.idle to get a response from the device to make sure there is actual communication? Have you actually gotten the Prop to make it play a song? Just want to make sure the bauds are right. I assume that you have a Prop board that does have a crystal(5m) so that the Prop is running at the right speed set in the CON.

One thing I just noticed, the code for that demo is for 4x20 LCD. The example to read 64 bytes and display it is for a 2x16 display. You need to specify which LCD you have. If you have the 4x20 then you could display 80 characters, so you could set the the array to 80, change the repeat serial.rxtime to 79 for a total of 80 bytes it can read and display at once.

jdshoe
01-19-2012, 03:16 AM
Hello,
I've spent more time on this and here is what I have so far. I ended up using the BS2 object in the main program to receive the data. I know it is not the best way to do this, but it works.
I am also able to play songs using the ump3 object.

In the ump3 object

PUB GetDir
'' Returns uMP3 file listing
if started
Serial.RxFlush ' flush any old receive stuff
Serial.str(String("FC L /Songs",13)) ' uMP3 get list

In the main program

BS2 : "BS2_Functions"

PUB Main

lcd.init(LCD_PIN, LCD_BAUD, LCD_LINES) ' Initialize LCD
lcd.backLight(true) ' Enable LCD Backlight
lcd.cls
waitcnt((clkfreq * 3) + cnt)
BS2.Start(29,28)
if uMP3.start(MP3RxPin,MP3TxPin,9600) ' start uMP3 (Rx,Tx,Baud)

uMP3.wait ' wait for idle
if uMP3.idle ' check that uMP3 is stopped
uMP3.GetDir
BS2.Serin_Wait(MP3RxPin,@listarray," ",9600,1,8)



This gives me the first file in the listing. Can you help me store the data from @listarray into another array SongList[x], so I can loop through file listing, increase x, and store the string to the next array element?

Thanks,
Justin