I just did some experiments - yes, as PhiPi says, global variables are updated if altered by other parts of the program.
There are still other possibilities. Questions about the hardware too. I can't test this as I don't have a keypad. Please send through your updated test code.
I post slightly edited Code that previous.
Read all my comments in it ---> I can't say I not understand You code --- But as usually every people/programmer have different approach how it can be done.
I can't say even that My one are better else bad. It is my logical solution to it NO more.
Here is another sample with FullDuplexSerialPlus instead of LCD display. It is not operating correctly. Baud rate is set correctly, but funny characters show up in the terminal window.
Sorry for "WAITPEQ and WAITPNE are not the same function" comment --- BUT as You see I not commented this line only added extra comment was unsure by my to!.
Post slightly edited Code that use Instead CALL to PUB MonitorKeypad for test possibility's.
The initial thread is also a necessity
Only if You need after this part functioning more code in it! else waste of COG.
As I said for possibility to test on my end this code I need Schematics to Yours "Keypad"
As LCD I can use My LCD TV.
commented out waitpeq
also commented out 'TimeDisplayCog := cognew(DisplayTimeAndDate, @TimeDisplayStack) + 1
this is the problem I talked about earlier where two methods are trying to output to the serial port at the same time. So you have to work out some way of only having one talk at once, even when debugging.
Also I ran this at 38400 baud but it should run at 115200
CON
_CLKMODE = XTAL1 + PLL16X
_XINFREQ = 5_000_000
OBJ
Debug : "FullDuplexSerialPlus"
VAR
BYTE Time
BYTE Date
LONG TimeTrackStack[32]
LONG TimeDisplayStack[32]
LONG KeypadCheckStack[32]
LONG PressedKey
LONG KeyPressed
LONG AbleToStopExample
LONG Reset
LONG ClockIsSet
BYTE TimeTrackCog
BYTE TimeDisplayCog
BYTE KeypadCheckCog
PUB BareBones
Debug.Start(31, 30, 0, 38400)
debug.str(string("start"))
WAITCNT(CLKFREQ * 2 + CNT)
KeyPressed := FALSE
AbleToStopExample := FALSE
Reset := FALSE
Debug.Str(STRING("cognew"))
KeypadCheckCog:= cognew(MonitorKeypad, @KeypadCheckStack) + 1
TimeTrackCog := cognew(TrackTimeAndDate, @TimeTrackStack) + 1
'TimeDisplayCog := cognew(DisplayTimeAndDate, @TimeDisplayStack) + 1
AbleToStopExample := TRUE
REPEAT
IF Reset == TRUE
COGSTOP(KeypadCheckCog~ -1)
WAITCNT(CLKFREQ * 3 + CNT)
REBOOT
PUB MonitorKeypad | k
DIRA[0..3]~
DIRA[5]~
REPEAT
'WAITPEQ(|<5, |<5, 0)
KeyPressed := TRUE
PressedKey := INA[3..0]
debug.str(string("press a key eg 8"))
k:= debug.rx
debug.tx(k)
if abletostopexample == true
debug.str(string("true"))
else
debug.str(string("false"))
IF k == "8" AND AbleToStopExample == TRUE
COGSTOP(TimeTrackCog~ -1)
COGSTOP(TimeDisplayCog~ -1)
Debug.Str(STRING("End Of Test"))
Debug.Tx(13)
Debug.Str(STRING("Goodbye"))
Reset := TRUE
QUIT
'WAITPNE(|<5, |<5, 0)
PUB TrackTimeAndDate | TimeResultString, DateResultString, AddOnString
REPEAT
Time := STRING("Time")
Date := STRING("Date")
PUB DisplayTimeAndDate
REPEAT
Debug.Str(Date)
Debug.Tx(13)
Debug.Str(Time)
Debug.Tx(13)
I did the same and that got it to work in Parallax Serial Terminal but not on the machine. The code represents that input is available from the keypad. It then obtains the bits on pins 0..3 to obtain the information about the key that was pressed.
If after initiating all things and no more need be run in COG-0 You add REPEAT before CALL to PUB MonitorKeypad it will run in its OWN COG = 0 that after all initiated are not used for any other thing
Good point --- It was one of questions in my comments to Yours code.
1. Code You need add --- are it ONE time code else need RUN repeated to.
2. For test possibility's of this part of code I think not necessary --- As I can see it You have REPEAT --- IF RESET at last in this function ----> Give same function as.
' CALL to MonitorKeypad PUB.
REPEAT
MonitorKeypad
[COLOR=green]{ MOVED to MonitorKeypad (Spare one COG) else never used.
[/COLOR] [COLOR=green] REPEAT
IF Reset == TRUE
COGSTOP(KeypadCheckCog~ -1)
WAITCNT(CLKFREQ * 3 + CNT)
REBOOT
}[/COLOR]
While I appreciate your effort and enthusiasm, I am getting tired of explaining. The MonitorKeypad must run in its own cog and the first function must call it and also stay alive till the machine is shut down.
Reboot will work in the location that you suggest, however it should not be necessary to move it.
In my logical thinking to move RESET to PUB MonitorKeypad I have some errors.
Look at this mod
[B]PUB[/B] MonitorKeypad [COLOR=teal] ' Even this line not nessesary IF COG-0 only used after starting LCD [/COLOR]and
' other COG's for only this part of program.
DIRA[0..3]~ [COLOR=red]( Bad comment )' RUN's in COG-0 no need to waste COG for it [/COLOR]
DIRA[5]~ [COLOR=teal]' For functioning in COG-0 this 2 lines need be moved to Init part of start function[/COLOR]
[COLOR=green] ' that give it start at once
' REPEAT NEED be commented out
[/COLOR] WAITPEQ(|<5, |<5, 0)
KeyPressed := TRUE
Now I'm confused ---- > WHY waste ONE COG for that last part of function in attached code if it is only thing after initializing all other things in First part of function are done (ONCE).
As after initializing that first part of this function it will be only thing this COG will stay in (FOREVER before reset Propeller)
While I appreciate your effort and enthusiasm, I am getting tired of explaining. The MonitorKeypad must run in its own cog and the first function must call it and also stay alive till the machine is shut down.
Reboot will work in the location that you suggest, however it should not be necessary to move it.
You said "enthusiasm" ----> Maybe You have readed in CNC Machines
That I to sample parts for my little ----> Personal CNC that I even have posted Picture on control panel I will use on it. That one is from old Epson stylus SX610FW.
And Yours Program/Experience in it will help even me.
While I appreciate your effort and enthusiasm, I am getting tired of explaining. The MonitorKeypad must run in its own cog and the first function must call it and also stay alive till the machine is shut down.
Reboot will work in the location that you suggest, however it should not be necessary to move it.
Thinking out loud - could it be hardware? I've just been through a forum search for the last few days but I can't see any schematics. My apologies in advance if you have already posted these. Any chance of a quick photo of the board and the schematic?
I know that. But as I said to You I don't have that LCD to test this driver not Yours KB schematics to wire my test equipment.
And test with thing's I have
as I don't have an LCD handy. Does it work without a cognew?
I guess yes. I haven't followed all the postings in this thread but what jumps into my eyes is
the str-method of LCD_16x2_4Bit.spin calls the method PRI CHAR (LCD_DATA)
and inside this method some bitbanging is done.
Now you put the call of the startmethod into the main-cog's code (cog 0)
This means IO-Pins are set in the IO-register of cog 0
PUB START
DIRA[DB7..DB4] := %1111 ' Set everything to output
DIRA[RS] := 1
DIRA[RW] := 1
DIRA[E] := 1
INIT
PRI INIT
'DELAY.pause1ms(15)
OUTA[DB7..DB4] := %0000 ' Output low on all pins
OUTA[RS] := 0
OUTA[RW] := 0
OUTA[E] := 1
OUTA[DB7..DB4] := %0010 ' Set to DL=4 bits
OUTA[E] := 0
INST4 (%0010_1000) ' Now that we're in 4 bits, add N=2 lines, F=5x7 fonts
CLEAR
INST4 (%0000_1100) ' Display on, Cursor off, Blink off
INST4 (%0000_0110) ' Increment Cursor + No-Display Shift
now you want to call the method string (char) from another cog. (cog 1)
inside this cog the IO-register has no setup (because method start was called from cog 0)
So for cog 1 the IO-pins are all still inputs and I guess that's the reason why nothing happens
All IO-pin related stuff should be done by one and the same cog.
Maybe it makes sense to think about a buffer-concept. There is one cog that does all the
LCD-io by reading a buffer. This routine checks for bytes in the buffer that have changed and just
send new if something has changed.
All other cogs do NOT call the lcd-methods directly but only writing into the buffer.
If I'm allowed to comment a bit more: You have done it the right way to narrow down the problem.
I prefer to develop code VERY modular. one method is doing ONE thing or a couple of things
but then they belong together closely. Then I test this modular piece of code to all strange kind of situations.
(in case of LCD.str this would be call it with a string-pointer that is zero. call it with a VERY big
string (more than double than the LCD can display at once), setting the cursor on the last char sending a big string etc.
If all this works and catches up strange situations properly I'm going on with the next part of the code.
This secures that a bug will be in the actual code (and not in a former piece of code) for 99% of all cases.
So for cog 1 the IO-pins are all still inputs and I guess that's the reason why nothing happens
All IO-pin related stuff should be done by one and the same cog.
Maybe it makes sense to think about a buffer-concept. There is one cog that does all the
LCD-io by reading a buffer. This routine checks for bytes in the buffer that have changed and just
send new if something has changed.
All other cogs do NOT call the lcd-methods directly but only writing into the buffer.
I agree 100%. I believe this is the situation.
For the sake of discussion. In the top object, I have two buffers named LCDLine1 and LCDLine2. Cog-0 should be the only cog allowed to communicate with the LCD object, whereas other cogs(1-7) are free to alter LCDLine1 and LCDLine2 at will. Am I correct to assume that this is what you are saying?
if you do not run out of COGs you could try my LCD-driver. It's maybe a little bit harder to use as the driver does not have the usual comfort-functions, but the demo code added should show you how it works. The thing with this driver is, that you can set it up in a way that it's functioning like a screen-buffer. You can simply write the string into this buffer and "by magic" it appears on the LCD. Of course you can also have more than one screen-buffer and switch between.
So, you could for example have one COG writing the time into a dedicated memory location of the screen-buffer. Another COG writes the coordinates of your machine to a different location ...
It also includes a nice demo for a menu as far as I remember.
if you do not run out of COGs you could try my LCD-driver. It's maybe a little bit harder to use as the driver does not have the usual comfort-functions, but the demo code added should show you how it works. The thing with this driver is, that you can set it up in a way that it's functioning like a screen-buffer. You can simply write the string into this buffer and "by magic" it appears on the LCD. Of course you can also have more than one screen-buffer and switch between.
So, you could for example have one COG writing the time into a dedicated memory location of the screen-buffer. Another COG writes the coordinates of your machine to a different location ...
It also includes a nice demo for a menu as far as I remember.
Comments
There are still other possibilities. Questions about the hardware too. I can't test this as I don't have a keypad. Please send through your updated test code.
I post slightly edited Code that previous.
Read all my comments in it ---> I can't say I not understand You code --- But as usually every people/programmer have different approach how it can be done.
I can't say even that My one are better else bad. It is my logical solution to it NO more.
- The initial thread is also a necessity
- WAITPEQ and WAITPNE are not the same function
BruceSorry for "WAITPEQ and WAITPNE are not the same function" comment --- BUT as You see I not commented this line only added extra comment was unsure by my to!.
Post slightly edited Code that use Instead CALL to PUB MonitorKeypad for test possibility's.
The initial thread is also a necessity
Only if You need after this part functioning more code in it! else waste of COG.
As I said for possibility to test on my end this code I need Schematics to Yours "Keypad"
As LCD I can use My LCD TV.
commented out waitpeq
also commented out 'TimeDisplayCog := cognew(DisplayTimeAndDate, @TimeDisplayStack) + 1
this is the problem I talked about earlier where two methods are trying to output to the serial port at the same time. So you have to work out some way of only having one talk at once, even when debugging.
Also I ran this at 38400 baud but it should run at 115200
I did the same and that got it to work in Parallax Serial Terminal but not on the machine. The code represents that input is available from the keypad. It then obtains the bits on pins 0..3 to obtain the information about the key that was pressed.
That is not the solution.
Bruce
If after initiating all things and no more need be run in COG-0 You add REPEAT before CALL to PUB MonitorKeypad it will run in its OWN COG = 0 that after all initiated are not used for any other thing
This is not the complete code. It is the code for a machine interface. More code will be added to the first function. Therefore it is necessary.
Bruce
Well then we are getting closer to the problem. The LCD display or the keypad.
Can you rewrite code so that it sends to both the LCD and the terminal at the same time? That will check the LCD.
Then test the keypad. I presume you have a one line bit of code that tests the keys actually work?
Good point --- It was one of questions in my comments to Yours code.
1. Code You need add --- are it ONE time code else need RUN repeated to.
2. For test possibility's of this part of code I think not necessary --- As I can see it You have REPEAT --- IF RESET at last in this function ----> Give same function as.
While I appreciate your effort and enthusiasm, I am getting tired of explaining. The MonitorKeypad must run in its own cog and the first function must call it and also stay alive till the machine is shut down.
Reboot will work in the location that you suggest, however it should not be necessary to move it.
Bruce
In my logical thinking to move RESET to PUB MonitorKeypad I have some errors.
Look at this mod
Now I'm confused ---- > WHY waste ONE COG for that last part of function in attached code if it is only thing after initializing all other things in First part of function are done (ONCE).
As after initializing that first part of this function it will be only thing this COG will stay in (FOREVER before reset Propeller)
You said "enthusiasm" ----> Maybe You have readed in CNC Machines
That I to sample parts for my little ----> Personal CNC that I even have posted Picture on control panel I will use on it. That one is from old Epson stylus SX610FW.
And Yours Program/Experience in it will help even me.
I now looked on Yours original "MachineInterface.spin" code and it is how I approach this solution.
This what I have determined through testing.
- The hardware is working fine. This was proven by outputing a string to the LCD without a new cog.
- The problem lies in the communication from a new cog to the LCD object.
Please see the attachment below titled "AbosulteBareBones". This code does not work!Bruce
Function for me - See attached files.
Again you are missing the point.
Therefore the problem lies in LCD : "LCD_16X2_4BIT"
not
LCD : "TV_Text"
Bruce
I know that. But as I said to You I don't have that LCD to test this driver not Yours KB schematics to wire my test equipment.
And test with thing's I have
I am glad it worked for you.
Bruce
as I don't have an LCD handy. Does it work without a cognew?
I guess yes. I haven't followed all the postings in this thread but what jumps into my eyes is
the str-method of LCD_16x2_4Bit.spin calls the method PRI CHAR (LCD_DATA)
and inside this method some bitbanging is done.
Now you put the call of the startmethod into the main-cog's code (cog 0)
This means IO-Pins are set in the IO-register of cog 0
now you want to call the method string (char) from another cog. (cog 1)
inside this cog the IO-register has no setup (because method start was called from cog 0)
So for cog 1 the IO-pins are all still inputs and I guess that's the reason why nothing happens
All IO-pin related stuff should be done by one and the same cog.
Maybe it makes sense to think about a buffer-concept. There is one cog that does all the
LCD-io by reading a buffer. This routine checks for bytes in the buffer that have changed and just
send new if something has changed.
All other cogs do NOT call the lcd-methods directly but only writing into the buffer.
If I'm allowed to comment a bit more: You have done it the right way to narrow down the problem.
I prefer to develop code VERY modular. one method is doing ONE thing or a couple of things
but then they belong together closely. Then I test this modular piece of code to all strange kind of situations.
(in case of LCD.str this would be call it with a string-pointer that is zero. call it with a VERY big
string (more than double than the LCD can display at once), setting the cursor on the last char sending a big string etc.
If all this works and catches up strange situations properly I'm going on with the next part of the code.
This secures that a bug will be in the actual code (and not in a former piece of code) for 99% of all cases.
best regards
Stefan
Thank you so much for responding!
I agree 100%. I believe this is the situation.
For the sake of discussion. In the top object, I have two buffers named LCDLine1 and LCDLine2. Cog-0 should be the only cog allowed to communicate with the LCD object, whereas other cogs(1-7) are free to alter LCDLine1 and LCDLine2 at will. Am I correct to assume that this is what you are saying?
Bruce
You were correct! That resolved the issue! THANK YOU VERY MUCH!
Bruce
if you do not run out of COGs you could try my LCD-driver. It's maybe a little bit harder to use as the driver does not have the usual comfort-functions, but the demo code added should show you how it works. The thing with this driver is, that you can set it up in a way that it's functioning like a screen-buffer. You can simply write the string into this buffer and "by magic" it appears on the LCD. Of course you can also have more than one screen-buffer and switch between.
So, you could for example have one COG writing the time into a dedicated memory location of the screen-buffer. Another COG writes the coordinates of your machine to a different location ...
It also includes a nice demo for a menu as far as I remember.
Let me know if you need some help.
http://obex.parallax.com/objects/576/
I like the way you described it. Sounds very nice. I'll check it out.
Thanks
Bruce
It is possible You can change discussion Thread Link to new Forum.
> http://forums.parallax.com/showthread.php?117059-Another-LCD-driver-%28HD44780%29