Well, I tested some more. Here's a stripped down, hopefully clear example program. I did check to see what the byte order was on the Propellor and I did have it backwards. It's <LSB,MSB> for words and <LSB,...,...,MSB> for longs. I corrected WriteWord and ReadWord and added WriteLong and ReadLong and tested all of them as you can see in the example. Load this into your Propellor EEPROM and repeatedly restart it to see what happens.
OK, I loaded in EEPROM and if ran fine.· Each time I restarted, all the numbers increased by 10.· Now what do you want me to do?· What changes do I have to make to WriteLocation and ReadLocation so they will do the same?
Simple, copy and paste the WriteByte, WriteWord, and WriteLong and the ReadByte, ReadWord, and ReadLong into your program. If it's not already there, copy and paste the CON declarations for EEPROM_ADDR, and the I2C pin numbers into your program. Copy and paste the i2cInit call into your main routine during the initialization stuff. Make sure that the values you want to preserve (like xpos and ypos) are declared in some DAT section, not a VAR section and that you give initial values like 0 that make sense.
At a point where you want to preserve the values (like xpos and ypos) across a power failure or restart, put a WriteWord(@xpos,xpos) and a WriteWord(@ypos,ypos). That's it! If you load the program from a PC into RAM, the initial values will be whatever you declare them to be in the DAT section. If you load the program from EEPROM into RAM (normal after power up), the first time the values will be whatever you declare them to be. Every time thereafter (unless you load from the PC), the values will be what was last saved before the power went off (or reset was pushed).
If, for some reason, you want to read the EEPROM directly into your program, you can put a x := ReadWord(@xpos) or y := ReadWord(@ypos) to return the values stored in EEPROM.
Yes, all you need is the Write... and Read... (if you use them), the global definitions including the OBJ i2ccontrol one, and the i2cInit call. Sorry for getting the bytes backwards.
PRI WriteWord(location,contents) · WriteByte(location+1,contents >> 8) · WriteByte(location,contents & $FF)
What is "location" and "contents"?· Is location the xposit or yposit I have in DAT?· It looks like this will just write one of my two values, xpos and ypos.·
You wrote:
PRI ReadWord(location) · return ReadByte(location+1) << 8 | ReadByte(location)
"location" is the address in the EEPROM to write the first byte of the data. "contents" is the actual data value to be written. When you call any of the "Write..." routines I've written, the first parameter must be the address of the first location in EEPROM to write. It turns out that the location of a quantity in RAM is the same as the location of that quantity in EEPROM since the Propellor just copies the first 32K bytes of EEPROM directly into RAM as part of the reset initialization if there's no PC present, but there's EEPROM hooked up to pins 28 and 29. If you want to save the value of a variable in a VAR or DAT section, first you need to have the address of the variable. If the variable is called "foo", the address is written "@foo". Then you need the value you want saved. Usually it's the current value of the variable in RAM, but it could be any other value. In your case I assume you want to save the current value of the variable in RAM. In your case, you want to save two word variables, call them "xpos" and "ypos". In your case, you've declared them in a VAR block although I suggested that you declare them in a DAT block. In your case it shouldn't make any difference. Forget "xposit" and "yposit". They're just confusing things. To save the current values of "xpos" and "ypos" in RAM to EEPROM so that they'll have the saved values when next the program is loaded into RAM from EEPROM by the Propellor chip on a reset do: "WriteWord(@xpos,xpos) and WriteWord(@ypos,ypos)". This will write 4 bytes to EEPROM from RAM (2 for each WriteWord call).
Regarding reading ... ReadWord reads two bytes and assembles them into a word for you. It's a function and returns the word it's just read as its value. You can do anything you want with it ... assign it to another variable, etc. To display the value using the tv text object ("OBJ txt : tv_text") just do "txt.dec(ReadWord(@xpos))". This will display the word value in EEPROM stored at the location where it will be loaded into RAM as the initial value of the variable "xpos" when the Propellor next resets.
Mike, I'm sure I must be a dosappointment to you but I can not get this I2C stuff to work.· I did exactly what I think you said - at the beginning of the program I wrote:
readword(@xpos) · term.dec(xpos)
and at the end of the "go left" sequence I wrote:
writeword(@xpos,xpos)
If I say left 50, the screen says xpos - 50, but if I turn the Prop off, then back on, everything goes back to 0, so it appears I'm either·not writing to EEPROM correctly or I'm not reading correctly.· The only way this is going to work is if yiu put the whole program together so it will be right.· If you don't have time to do it, that is OK.· I'll just go back to Revision N which has no I2C in it at all.
Sorry about that but I really tried.· I guess I don't really understand what you are trying to tell me, which is my fault, not yours.
Please take out the "readword(@xpos)". You don't need it at that point in the program. The "term.dec(xpos)" should show you the initial value of xpos. This is either zero (if the program was just downloaded to RAM or just written to EEPROM, then copied to RAM) or the previously saved value. You might put a "term.dec(xpos)" just before the "writeword(@xpos,xpos)" to verify that xpos has what you expect at that point. If you post your whole program, I'll try to have a look at it tomorrow.
Mike, revision R is attached.· I made the deletion and addition you suggest.· If I say left 50, the screen says "New xpos = 50", but if I turn Prop off then back on, everything says 0.· Only the go left sequence has the I2C commands.· Once I see how you do it, I can make the changes to the other sequences.
I think the problem might be in the WriteWord and ReadWord definitions:
PRI WriteWord(location,contents)
WriteByte(@location+1,contents >> 8)
WriteByte(@location,contents & $FF)
PRI ReadWord(location)
return ReadByte(@location+1) << 8 | ReadByte(location)
Don't put the "@" before location in the calls to ReadByte and WriteByte. The location parameter is already an address. Using @location is the address of the address, which is not what you want.
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔ OS-X: because making Unix user-friendly was easier than debugging Windows
Ok, so that means there's an additional problem. But you definitely don't want the "@" sign in the calls to WriteByte and ReadByte. I'll take a look at the program and see if I can find the other problem.
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔ OS-X: because making Unix user-friendly was easier than debugging Windows
A couple things jumped out at me. You've got xpos, ypos, xposit, and yposit defined in your VAR section and you also have xposit and yposit defined in the DAT section. If I've read it correctly, Mike's method of reading and writing values to the EEPROM only works for things defined in the DAT section. What I would do is remove all definitions of xposit and yposit and define xpos and ypos in the DAT section.
replace "xposit" with "@xpos" and "yposit" with "@ypos" in the calls to writeword.
Also, you can replace "xpos := xpos + dist" with "xpos += dist" (and likewise for the other assignments). The difference probably isn't significant in this particular application, but I thought I'd point it out.
Sorry but I'm not able to get my setup to where the TV is right now, so I can't test the program myself.
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔ OS-X: because making Unix user-friendly was easier than debugging Windows
Sid and I worked on this via email and it turned out (among other problems) that the I2CObject's Init method was never being called. Here's a version that remembers xpos and ypos between sessions.
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔ OS-X: because making Unix user-friendly was easier than debugging Windows
I ran Rev S and it looks like it is working great !!· Tried out the DIP function and that worked OK, too.· Turned the Prop off, then back on, and the current positions were there - fantastic!
Auto run will be no problem.· It has its own method and has to be run from start to finish in one run.· There is no way I can turn the Prop off, then pick up where I left off.
I have two questions:
When I'm doing a board the "trav" data list might be 250 lines.· Is it OK to move the DAT block to the very end?
If I'm starting a new board with a new piece of copper, I can always position the cutter where I want to start etching - 0, 0 with reference to my piece of copper.· However, the real xpos and ypos could be any value.· Is there any way to reset xpos and ypos to 0.· I can always turn off the stepper motors, then run the program so that xpos and ypos are 0, then turn the steppers back on, but I just wondered if there is any way to do it in the program.
I'll have to study Rev S a bit to see how it really works but I am very pleased with the results.· Thanks very much to you, Steve, and to you, Mike.
Now I can really play around.
And concentrate of interfacing the Prop to SuperMill.
You have to be able to tell the program what you want. Is there a pushbutton (and a pin to use for input) that would mean "Reinitialize the program". Rewriting EEPROM using the Propellor Tool will also reinitialize everything, but do you want to do that? How do you get the data list into the Propellor? If you use the Propellor Tool (and the data list in the source program), you can easily just reload the whole thing.
The DAT block is often put at the very end, particularly when it has assembly language in it, but you can have more than one DAT block and they can be placed anywhere a block (CON/DAT/VAR/PRI/PUB) is allowed.
Newzed said...
Something like this, maybe:
...
if selection == "C" 'added
changexpos(0) 'added
changeypos(0) 'added
No, it has to be changeXpos(-xpos) and changeYpos(-ypos) like I originally said. If you look at the changeXpos/changeYpos methods, you'll see that they add the parameter to xpos and ypos. Your code would have no effect on the values of xpos and ypos.
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔ OS-X: because making Unix user-friendly was easier than debugging Windows
Now I get it, Steve.· "changeXpos(value)" really means "changeXpos by the amount of (value)".· It does not mean "changeXpot to (value)".
So xpos + (-xpos) = 0.
I'll incorporate these changes first thing this morning.· Thanks.
Yeah, term.dec takes a long parameter so you have to sign-extend xpos because it's a word. You could change xpos to a long to avoid having to do that. If you do, be sure to changeXpos to call WriteLong instead of WriteWord.
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔ OS-X: because making Unix user-friendly was easier than debugging Windows
The finished program has one PUB and 17 PRIs.· Is the cog usage one for PUB, plus one for whatever PRI has been called.· In other words, is the program using a max of 2 cogs at any given time?
Nope. The program we wrote is all running on one cog. The only time another cog is started is when the program calls Cognew or Coginit.
Of course some of the objects the program uses are running in separate cogs, but I haven't gone through those objects to count up how many cogs they are using.
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔ OS-X: because making Unix user-friendly was easier than debugging Windows
No, there is no correspondence between the number of objects and the number of cogs. A single cog can run any number of objects and a single object can use one or more cogs.
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔ OS-X: because making Unix user-friendly was easier than debugging Windows
Comments
Sid
At a point where you want to preserve the values (like xpos and ypos) across a power failure or restart, put a WriteWord(@xpos,xpos) and a WriteWord(@ypos,ypos). That's it! If you load the program from a PC into RAM, the initial values will be whatever you declare them to be in the DAT section. If you load the program from EEPROM into RAM (normal after power up), the first time the values will be whatever you declare them to be. Every time thereafter (unless you load from the PC), the values will be what was last saved before the power went off (or reset was pushed).
If, for some reason, you want to read the EEPROM directly into your program, you can put a x := ReadWord(@xpos) or y := ReadWord(@ypos) to return the values stored in EEPROM.
Sid
PRI WriteWord(location,contents)
· WriteByte(location+1,contents >> 8)
· WriteByte(location,contents & $FF)
What is "location" and "contents"?· Is location the xposit or yposit I have in DAT?· It looks like this will just write one of my two values, xpos and ypos.·
You wrote:
PRI ReadWord(location)
· return ReadByte(location+1) << 8 | ReadByte(location)
Don't I need to read another byte?
How do I display what I have read?
Sid
Regarding reading ... ReadWord reads two bytes and assembles them into a word for you. It's a function and returns the word it's just read as its value. You can do anything you want with it ... assign it to another variable, etc. To display the value using the tv text object ("OBJ txt : tv_text") just do "txt.dec(ReadWord(@xpos))". This will display the word value in EEPROM stored at the location where it will be loaded into RAM as the initial value of the variable "xpos" when the Propellor next resets.
readword(@xpos)
· term.dec(xpos)
and at the end of the "go left" sequence I wrote:
writeword(@xpos,xpos)
If I say left 50, the screen says xpos - 50, but if I turn the Prop off, then back on, everything goes back to 0, so it appears I'm either·not writing to EEPROM correctly or I'm not reading correctly.· The only way this is going to work is if yiu put the whole program together so it will be right.· If you don't have time to do it, that is OK.· I'll just go back to Revision N which has no I2C in it at all.
Sorry about that but I really tried.· I guess I don't really understand what you are trying to tell me, which is my fault, not yours.
Sid
Thanks
Sid
Don't put the "@" before location in the calls to ReadByte and WriteByte. The location parameter is already an address. Using @location is the address of the address, which is not what you want.
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
OS-X: because making Unix user-friendly was easier than debugging Windows
links:
My band's website
Our album on the iTunes Music Store
Sid
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
OS-X: because making Unix user-friendly was easier than debugging Windows
links:
My band's website
Our album on the iTunes Music Store
In this code:
replace "xposit" with "@xpos" and "yposit" with "@ypos" in the calls to writeword.
Also, you can replace "xpos := xpos + dist" with "xpos += dist" (and likewise for the other assignments). The difference probably isn't significant in this particular application, but I thought I'd point it out.
Sorry but I'm not able to get my setup to where the TV is right now, so I can't test the program myself.
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
OS-X: because making Unix user-friendly was easier than debugging Windows
links:
My band's website
Our album on the iTunes Music Store
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
OS-X: because making Unix user-friendly was easier than debugging Windows
links:
My band's website
Our album on the iTunes Music Store
Auto run will be no problem.· It has its own method and has to be run from start to finish in one run.· There is no way I can turn the Prop off, then pick up where I left off.
I have two questions:
When I'm doing a board the "trav" data list might be 250 lines.· Is it OK to move the DAT block to the very end?
If I'm starting a new board with a new piece of copper, I can always position the cutter where I want to start etching - 0, 0 with reference to my piece of copper.· However, the real xpos and ypos could be any value.· Is there any way to reset xpos and ypos to 0.· I can always turn off the stepper motors, then run the program so that xpos and ypos are 0, then turn the steppers back on, but I just wondered if there is any way to do it in the program.
I'll have to study Rev S a bit to see how it really works but I am very pleased with the results.· Thanks very much to you, Steve, and to you, Mike.
Now I can really play around.
And concentrate of interfacing the Prop to SuperMill.
Sid
The DAT block is often put at the very end, particularly when it has assembly language in it, but you can have more than one DAT block and they can be placed anywhere a block (CON/DAT/VAR/PRI/PUB) is allowed.
That will reset xpos and ypos to zero and write zero to the EEPROM.
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
OS-X: because making Unix user-friendly was easier than debugging Windows
links:
My band's website
Our album on the iTunes Music Store
term.str(string("L - Left (X axis)",13))
· term.str(string("R - Right (X axis)",13))
· term.str(string("I - In (Y axis)",13))
· term.str(string("O - Out (Y axis)",13))
· term.str(string("U - Up (Z axis)",13))
· term.str(string("D - Down (Z axis)",13))
· term.str(string("H - Drill 1 hole",13))
· term.str(string("S - Drill SIP or DIP",13))
· term.str(string("A - Autorun, 13))
· term.str(string("C" - Reset X and Y,13,13))··· 'added
and then:
if (selection == "U")
··········· stepDirection := ZUp
········· else
··········· stepDirection := ZDown
········· if selection == "C"····· 'added
··········· changexpos(0)····· · 'added
··········· changeypos(0)····· · 'added·
Sid
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
OS-X: because making Unix user-friendly was easier than debugging Windows
links:
My band's website
Our album on the iTunes Music Store
So xpos + (-xpos) = 0.
I'll incorporate these changes first thing this morning.· Thanks.
Sid
until (lookdown (selectedOption : "LRIOUDHSAC"))·· 'added C
Now it works fine.
One more thing -· if I am at x = 0 and I enter R 100, the table will go to
X = -100 but the screen says X = 65436.· I tried writing:
··term.str(string("····· X = "))
· changeXpos(~~xpos)
· term.dec(xpos)
but that didn't work.· How do I display X and Y as signed integers?
Sid
· term.str(string("····· X = "))
· term.dec(~~xpos)
and that seems to work.·
Sid
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
OS-X: because making Unix user-friendly was easier than debugging Windows
links:
My band's website
Our album on the iTunes Music Store
Thanks
Sid
Of course some of the objects the program uses are running in separate cogs, but I haven't gone through those objects to count up how many cogs they are using.
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
OS-X: because making Unix user-friendly was easier than debugging Windows
links:
My band's website
Our album on the iTunes Music Store
Sid
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
OS-X: because making Unix user-friendly was easier than debugging Windows
links:
My band's website
Our album on the iTunes Music Store
Going down 185···
I wrote:
PRI drillHole
· term.str(string("Going down "))
· term.dec(HoleDepth)··· 'HoleDepth is a CON = 185.0
The screen says:
Going down 112780902
Why doesn't it say 185?· As far as I can tell, there have been no manipulations of HoleDepth up to this point.What am I doing wrong?
Sid
··term.dec(TRUNC(HoleDepth))
-Phil