Reading and Writing an array, see well documented "Spin" file attachment.
JMLStamp2p
Posts: 259
Hello,
I am trying to read and write to and array via a Matrix Keypad to a serial LCD.
The "Spin" file is attached and is well documented. Please give example code with comments as to where I am coding wrong.
A complete explanation is given in the Header at the start of the file as to what my objective is and comments are under each line of code as to how I understand it at present.
Thanks,
JMLStamp2p
I am trying to read and write to and array via a Matrix Keypad to a serial LCD.
The "Spin" file is attached and is well documented. Please give example code with comments as to where I am coding wrong.
A complete explanation is given in the Header at the start of the file as to what my objective is and comments are under each line of code as to how I understand it at present.
Thanks,
JMLStamp2p
Comments
I had three remarks the other week wrt your code I can repeat repeat:
(A) I doubt that this keypad of yours it working with 19200 baud
(B) I asked you to fix the wrong definition of dataIn
(C) Why are you crippling your Procesor to 5MHz? This is close to the limits of even FDserial to handle 19200 baud.
Nevertheless (B) and (C) are hardly the reasons for your errant readings, but morte likely (A)
1) The Keypad is definately working at 19200 Baud, I can see it working and have varified it with the Matrix Orbital.
2) I did change the datain line of code, I am passing the address of datain to the rxStr method because that method will need to
write data to the array later on.
3) I had the processor at *16, and also tried *8 just to see if it made a differance and it made none.
Have you looked at the "Spin" file attachment with the last post ?
And if you would, An example of how to pass the address of an array to a method and then an example of how to read
locations within that array would be very helpfull !
Your help is greatly appreciated !
Thanks,
JMLStamp2p
This is the problem: I see no issue in your code! That you keep allocating 2 bytes where no need 4 is not an issue at the moment..
When you say: your display of the received character's DEC gives you different values, then it's either the hardware or something really more complex....
I think the keypad is a 5V device. You most likely use a serial resistor. This can be too large.. 10k will do fine
I have inline resistors on the transmit & recieve side of the serial display per Chris Savage at Parallax. I might not have explained myself right at the beginning, I do not want my array to ever hold more than 3 bytes. I would like to have the array cleared after recieving 3 bytes and then written again. I have tried increasing the command to byte datain[noparse][[/noparse]16] and when I tried this I got a whole lot of garbage on my display.
I thought about what you said concerning the clock speed and remembered that it did work fine " as far as the keypad sending the correct characters" when my clock speed was * 16. Could this really be messing up everything ! I sure hope that it is that simple, I will try changing it first thing in the morning and see what happens...
Sure appreciate your help,
JMLStamp2p
When you declare an array, example: byte datain
Is this not location 0, 1 and 2
being 3 locations for bytes ?
JMLStamp2p
long/word/byte arrayName[noparse][[/noparse]n]
The indexes go from 0 to n-1
So in your case
byte string[noparse][[/noparse]3+1]
The +1 is because you will need a null at the end if you are going to use the numbers routines to turn a string into a number. Also, you talked about using decimal numbers which will need another character.
byte datain[noparse][[/noparse] 2]
JMLStamp2p
Thank You for your help !
JMLStamp2p
You could easily avoid such discussions
I also said that this is not an issue (@John: Do you se why not? It has to do with BYTES and LONG alignment...)
Post Edited (deSilva) : 2/22/2008 11:57:34 PM GMT
However this keypad is tricky with some build-in intelligence and said "reprogrammable".. There is another thread where this issue has - successlessly - tried to be solved...
Post Edited (deSilva) : 2/23/2008 12:27:36 AM GMT
The Serial LCD from Matrix Orbital is not a standard LCD. It's baud rate is programable up to 57K and also supports not standard baud rates. It has a built in buffer and also supports up to a 5 by 5 Matrix
Keypad directly. The output ASCII codes are not standard as far as the corresponding digits are concerned. This is a very evolved LCD and has many programable features.
JMLStamp2p
Your statement was as follows:
You are reading and storing 3 characters. datain is only 2 long.
I am interested in learning the details of code. I understood exactly what you were saying in the above thread concerning the bytes in the arrray. You did not go into the details as why and therefore I did not
understand about the null characters needed. In the following example by stevenmess2004 he gives a
little more deatail which makes it very clear.
For any array of n elements you declare like
long/word/byte arrayName[noparse][[/noparse]n]
The indexes go from 0 to n-1
So in your case
byte string[noparse][[/noparse]3+1]
The +1 is because you will need a null at the end if you are going to use the numbers routines to turn a string into a number. Also, you talked about using decimal numbers which will need another character.
THANK YOU !
I changed my clock to: _CLKMODE = XTAL1 + PLL16X & _XINFREQ = 5_000_000
and the whole program started working correctly ! The Keypad and display are doing exactly what it is suppose to be doing. I would not have thought that I was that close to a timing constraint. I also changed my array declaration to: byte datain[noparse][[/noparse] 5].
Guys,
Can anyone give me an example of how to read & write a number with a decimal point into the array ? example: "123.5"
My project requires that I load a "Count down" number in the array which is being done now "Thankyou Jesus" ! and compare it to the system clock to countdown in 1/10th of a sec. intervals.
Thankyou guys for your help !
JMLStamp2p
to output a decimal point before the last digit. The intention is to show the integer
value as something in units of 1/10th. Normally the output routine will always put
out at least one digit. This is modified to put out two digits, so there's always a
digit before the decimal point (like "0.5").
You should be able to figure out how to store the characters into an array instead of being transmitted out a serial port.
Post Edited (Mike Green) : 2/23/2008 1:50:47 PM GMT
Note that dimensioning a vector is not always so strict, and sloppiness can stay undetected for a long time!
As 4 characters are put into one long, there is often some "padding" and you can use unclaimed space.
However be warned of another easily forgotten peculiarity of SPIN:
In the VAR section your labels can be RE-ARRANGED against your most basic intuition. The rule is:
LONGs first, then WORDs, at last the BYTEs. So your adding of "delimeter" was of no use, it had been secretely reshifted BEFORE the BYTE-vector!
WRT to number conversion: You have to convert decimals to an integer value as well as the "cont-down" back to characters (including a decimal ).
It is no major problem to code this straightforward, but you can also use the object NUMBERS. It might take you some hours to understand its working but is will save you tremendious time later AFTER you have learned how to use it.
Post Edited (deSilva) : 2/23/2008 1:55:29 PM GMT
The simplest thing is to just ignore the decimal point character. That way, 99.0 and 990 are the same.
The other option is to have a "decimal places" counter. This would be a modification of say the Extended FullDuplexSerial input routine. The counter is initially set to zero. When a decimal point character is found: If the counter is non-zero, it's an error. If the counter is zero, it's incremented. When a decimal digit is processed: If the counter is non-zero, it's incremented.
When the number is finished (like when a carriage return is found), the "decimal places" counter should be zero or one. If one, the result is already in units of tenths and you don't have to do anything. If zero, multiply the result by 10.
Thanks, I was not aware of that.
Mike,
I always need the decimal but it does not have to be checked. I have attached the up-dated version of the working "Spin" file to this reply. I am sure that my code could be written more efficiently but right now I'm just glad everything is working :>). I am going to take a look at the "Numbers" Object and start trying to learn it.
If you guys could look at the current up-loaded file and give advice it would be appreciated. I am really just now kinda getting into the groove with Spin so there's still alot of "Cloudy" water to tread through.
Thanks so much,
JMLStamp2p
PUB Main | Value
cognew(Recieve(1,0,2,9600),@Stack)
'Start new cog to run the Recieve method
'Independantly
My Recieve method below:
PUB Recieve(R_Pin, T_Pin, Mode, Baud) | rxbyte
repeat
rxbyte := data.rx
if rxbyte == 123
data.tx(01)
if rxbyte == 456
data.tx(02)
When I add these lines of code, my LCD display does not run correctly (getting alot of trash). Am I coding something wrong. Shouldn't my Recieve method be running in a seperate cog all togather Independantly from cog "0" running the rest of "Mains" code ?
JMLStamp2p
New cog for the·Recieve method·installed, Recieve method is at the very bottom. Up-loaded this file to make it easier to read for everybody, when I try and run with this code added my LCD behaves eratically. Can someone tell me where I am going wrong.
JMLStamp2p
there is still some confusion in your code...
(a) Never use a stack less than 20 LONGs, unless you know what you are doung
(b) Don't recur to MAIN - that is forbidden recursion in this case!
(c) One does not CALL a COG. CONEW "installs" a program which in most cases consists of an endless loop, but can be also a one shot, but NEVER returns a value.
Post Edited (deSilva) : 2/24/2008 5:25:35 PM GMT
(a) I will change my Stack to 20
(b) As far as recuring to Main, do you mean that a Method should not loop back to Main ?
(c) I would like my Reciever method to do nothing but run in a cog by itself, I am passing bytes back and forth between "2" Props
through a pair of spread spectrum Trancievers. I therefore want one cog dedicated to do nothing but look at the data
coming in the port. How can I do this correctly ?
Thanks for your help as always,
JMLStamp2p
It is very advanced concept in some languages ("taill recursion") not in SPIN, of course.
You have to organize your loops inside "main"!
(c) You just have to store the received bytes to a global variable (or a vector), not to the local result variable!!!
Thank you for the code you posted above concerning the decimal point. I will study this and try and incorperate it in my code. I am sending bytes back in forth between two props via spread spectrum trancievers hense the need to send the data out the port.
My project consist of entering a number from 0-999 from the Keypad, turning that number into a dec. equivalent and transmitting it to the remote prop. The remote prop will then use this number to compare against a decrementing counter and turn on an output which will drive a motor through the correct interface circuitry. I am trying to write the program so that I can use it in both Props to transmit and recieve the number to each other. We have "3" timers that turn on water to "Quench" our Coal at present, this program will take the place of those timers in software.
End Result:
To Enter "3" numbers, each with one decimal place into the Prop via the Keypad from either location.
Upon pressing the "D" button on the Keypad, Transmit these "3" numbers to the other Prop.
The Prop on at the Quenching station will look at "3" inputs via limit switch's for a High level logic input.
Depending on which limit was set, turn on a motor for a length of time corresponding to the "3" numbers or "Timer Values" that are stored in memory.
One prop "Not the one that is at the quenching station will be in our Supervisors office. He will need to see the counters counting down in his office as they are counting down at the quenching station. Thus my program will need to send the numbers as they are counting down at the quenching station via the "RF" link to our supervisors office. He will also be able to set timer values at his office and Transmit them to the quenching station. I am attempting to write "1" program that can run in both Props that accomplish this task.
This program is a pilot project for our Plant, if we can write this program to work efficiently we will be released to build many project using the Propeller. It is therrefore Very Important to me and your help with the code is Much appreciated.
JMLStamp2p
I have tried using Global varibles "TValue_1" ect. to attempt this, but still learning :>)
Thank You for your help.
JMStamp2p
I have the LCD attached and writing the results of whats being entered to the screen for confirmation, I also have a O'Scope attached so I can see the data output and check whats being input on the recieving end. After the Math statement of code I am getting the right results out of the Prop to the LCD so I know that the "3" numbers that I am entering via the Keypad are getting into the Array, ect.
The piece of code I need the most right now is the "Recieve method" so that I can take the "3" bytes recieved and input them into an array on the recieving end, do the math and display it to the LCD. At the moment I have a "Bare bones" recieve method incorperated on the recieving end but still need to do some work with it, "See last attached Spin file". I have exactly the same setup on both ends, Tranciever, Prop proto board & LCD. The Trancievers are Maxstream 900 Mhz "Virtual Wire" trancievers
and very reliable. They have built in buffers as the LCD is also buffered. The communication link is very reliable as I have been using them for a couple of years now.
I would like for the Props to run the recieve method in a seperate Cog for "RF" dependability.
Mike, I appreciate all the help you are giving, it is invaluable.
JMLStamp2p