would anybody share his SPIN-Code reading multiple DS1820 1-Wire-devices
StefanL38
Posts: 2,292
Hi,
I want to realise a easy to configure temperature-data-logger for DS1820-temperature sensors.
DS1820-sensors have digital output based on the 1-Wire-protocol.
I'm crawling my way through the 1-wire-bus-protocol. I estimate I understand half of it.
FullDuplexSerial is an object you can just use without understanding the details of the bitbanging.
I would like to do the same with 1-Wire. So I'm asking if somebody would share his ready-to-use 1-Wire-Code
The code should not only have a small demo of how to read ROM-IDs or read one temperature without checking the ROM-ID
That's what can be found in the OBEX and what I have already loaded and testet.
I don't wnat to RE-invent the wheel again. So I'm asking:
has somebody coded ready to use routines that do:
- scan the 1wire-bus for all devices connected, storing all the ROM-IDs of all found devices for later use in an variable-array
- methods that do all the details of how to read a temperature from a particular DS1820-device selected through its ROM-ID
(sending reset, sending ROM-ID, initiate temperature-conversion, wait for conversion to be finished, read temperature-value from scratch-pad,
,checkif CRC is OK)
- reading the 9bit temperature-value, reading the 12bit temperature value
- and maybe even methods that write data to the Th and Tl registers, read/write to EEPROM
If somebody can provide code like this I will extend comments in the code to make it easier to understand how it works
and will share my complete code which will add a configurable datalogger
first version sending data via serial interface push in regular time-intervals
or send data on request,
later version storing data on SD-card
best regards
Stefan
I want to realise a easy to configure temperature-data-logger for DS1820-temperature sensors.
DS1820-sensors have digital output based on the 1-Wire-protocol.
I'm crawling my way through the 1-wire-bus-protocol. I estimate I understand half of it.
FullDuplexSerial is an object you can just use without understanding the details of the bitbanging.
I would like to do the same with 1-Wire. So I'm asking if somebody would share his ready-to-use 1-Wire-Code
The code should not only have a small demo of how to read ROM-IDs or read one temperature without checking the ROM-ID
That's what can be found in the OBEX and what I have already loaded and testet.
I don't wnat to RE-invent the wheel again. So I'm asking:
has somebody coded ready to use routines that do:
- scan the 1wire-bus for all devices connected, storing all the ROM-IDs of all found devices for later use in an variable-array
- methods that do all the details of how to read a temperature from a particular DS1820-device selected through its ROM-ID
(sending reset, sending ROM-ID, initiate temperature-conversion, wait for conversion to be finished, read temperature-value from scratch-pad,
,checkif CRC is OK)
- reading the 9bit temperature-value, reading the 12bit temperature value
- and maybe even methods that write data to the Th and Tl registers, read/write to EEPROM
If somebody can provide code like this I will extend comments in the code to make it easier to understand how it works
and will share my complete code which will add a configurable datalogger
first version sending data via serial interface push in regular time-intervals
or send data on request,
later version storing data on SD-card
best regards
Stefan
Comments
I freshened up an old demo (from 2009) with a method that shows you how to read a specific sensor on a multi-sensor buss. I've used this code in the past, but couldn't test it today because I do not have sensors. It might need a little tweaking.
If you modify my 1W object, take my name off of it before posting. I'm willing to support my own code and comments, but not yours.
thank you very much for your code.
I analysed it. I understand most of it.
But there are still some questions left:
How do I code scanning the 1Wire-Bus for ALL devices that are connected to the bus?
As soon as two 1Wire-devices are connected to the bus your code responses with "bad CRC"
best regards
Stefan
SpinOneWire.spin
That is a fairly complicated process that I actually did once with a BS2p, but haven't with a Propeller. If you're producing a commercial product for others, you get the joy of reading the Dallas/Maxim spec for 1-Wire buss searching and implementing it in Spin. Again, I did it in PBASIC, so it's completely possible.
Any code that uses SKIP_ROM is not intended for multiple devices. Included in the code is a method called read_tca() which allows you to address a specific device. You need to use that.
I thought you wanted to understand the details of bit-banging 1-Wire. Well, my object shows you how with very plain code. It's up to you to do the rest for your project. If this is a personal (not commercial) project, you can insert one sensor at a time to read the serail #. One you have all the serial #s for your devices, you can create a program that round-robin scans them.
well my initial question was if somebody has finished and working well code that scans the whole bus and reads all the devices.
Seems not to be so. I did another intensive search in the OBEX and found object #81 http://obex.parallax.com/object/81
"1-wire device interface routines and demos. Low-level routines include network device search and CRC-8 calculation."
There is a demo included that shows how to scan the bus. This means there is a function "scan the whole bus" available
This object is from from Cam Thompson. Hi Cam! (winking my hands) thank you very much for your code.
As nobody has posted code like described above my next step is to code it on my own
how to store all the adresses found through bus-scan and
finding out how to send the right bytesequence for reading a particular device.
I guess Jon's code read_tca shows most of it. Still some work to be done.
@Moskog: Thank you very much for sharing your code.
Somehow I prefer to use PASM-routines for the bitbanging. Though for me it's harder to understand how PASM works than how spin works
If I have coded everything I will share it here in the forum or the OBEX.
In this forum all support is for free. So I'm far away from complaining about something.
Anyway I would like to say that more comments in the code will make it much easier to understand.
I want to give an example of what I mean:
This CODE is a part of Jon's 1-Wire-code. (Comments are NONSENSED by me (Stefan)
Of course everybody is free to do as much or less comments as she/he wants
because nobody gets any extra money and mostly no extra honour for extra commenting.
But I want to give an impulse with asking: how about adding some extra comments making it easier to understand?
best regards
Stefan
' store hub-addr of start of longs defined in SPIN in "r1"
...are complete nonsense.
How about cracking open the documentation -- like those of us who create objects do -- and studying it? Do you think I just woke up on morning and wrote that 1-Wire code? While I have done that with a couple short movie scripts, I've never done that with software. To me this "Hey, how about extra commenting?" thing says that people don't really want to understand, what they want is to be relieved of the burden of self-study. It's the Arduino syndrome: people that cobble together pre-written program fragments and want to declare themselves "programmers." This is why I stopped uploading my objects to ObEx -- and why I'm going to stop sharing my objects in the forums.
I agree with you. I can't count how many times I've seen this ADD value,#5 ' Add 5 to value
It's like "No duh...Tell me something I didn't know."
As for people just using libraries, I think that is fine for beginners, but the problem is that you have little knowledge of what is really going on. This is why people demand more and more memory and faster and faster processors so they can just lump in a bunch of libraries and make something happen.
Oh, sometimes I long for the days of writing assembly language on my Timex Sinclair 1000, where every byte and every cycle counted. I worked for several months as a kid working on a space invader game. I learned so much about programming by making it fit in 2K and making it fast and responsive.
Bean
I'm sorry if my posting made you upset. (sounds like that). That was not my intention.
I asked for opinions and you gave a clear answer. Thank you for that.
Something beeing "obvoius" depends on the knowledge somebody already has.
To me the differences of how much somebody knows or how much he should know is only gradually.
Do I have to have designed the inner circuitry of a chip before I'm ready to use one?
How much complexity must this self-designed chip have? Transistor?, OP-Amp? Propeller-Chip?
Only If I have designed or studied the inner circuitry of the propeller-chip in deep details I will be able
to forseeing the sensivity of the PLL-ciruictry that will make me taking precautions to avoid killing it.
The other option is to kill it once or twice and learning it when nescessary. It's the same thing to me with software.
If I don't understand how to use it I will code bugs and if bugs occure the bug will make it nescessary to go deeper inside.
Do I really have to study this deep before I'm ready to use the propeller-chip?
Do I have to have coded a compiler myself before I'm ready to use one?
Now where is the PRINCIPAL difference between putting code-fragments together without understanding all details
of what the code does and studying the inner circuitry of the propeller-chip?
As my posting seems to have made you upset feel free to set me on the ignorelist if you want.
If you would like to explain where you see the principal difference please explain.
best regards
Stefan
P.S: In the meantime Bean chimed in.
So the only way to learn effective coding is to do everything from scratch? How about well commented code explaining how it can be done effective?
The commenting would allow to understand it faster making it easier to chime in and tweak the existing library (to make it faster or more responsive or whatever)
I said that using libraries is "fine for beginners". The problem is that when you must create something from scratch, the amount of work needed seems crazy. So people tend to only do things if a library exist for it. I don't want to speak for Jon, but I think his issue is "Live by the library, die by the library." or don't become dependent on libraries.
And yes, by doing everything from scratch, you will learn much more than using a bunch of libraries.
And don't waste your time writing comments that just echo WHAT the instruction is doing. Comments should explain WHY something is being done, not WHAT is being done. The "what" is obvious, the "why" is not.
Bean
People can see what the instructions literally do. Unless an odd use case, or trick is in use, it's better to comment their intent. People can always find the strict operation that happens. It's much harder to parse what that means in the context of the program overall.
I haven't evaluated this code and just took a stab at what that instruction intent might be for this case. If it's off, that's why.
Somewhere else, these pointer addresses should be listed as whether or not they are read, write, or both.
User can then read this block of code, understand the flow of data and it's purpose. That's what they really need to proceed or modify or use this code block.
Okay, this made me laugh -- you want me to write better comments so that you can understand my libraries to make them faster or more responsive? Thank you -- I needed a good laugh. That's not to say you aren't capable of improving my libraries, I just don't get the impression you're at that point yet when you're wrapped around the axle demanding comments for obvious code.
I'm with Bean: live by the library, die by the library. If one has the ability to make a library "faster or more responsive" the amount of commenting doesn't really matter. Do I write everything from scratch? No, I use a couple off-the-shelf libraries, but the only one I have not modified is FSRW because I haven't taken the time to fully understand it. I modified FullDuplexSerial to my liking (flexible buffer size, and added some high-level methods). I obviously couldn't have modified Chip's PASM code if I hadn't taken the time to learn what the instructions do, and also have a grasp on the mechanics of serial communications.
In my opinion, listings are not training material per se, they are supplements to training materials. Evey other month I write a column for Nuts & Volts magazine on Spin/PASM programming. Do you really think that I should spend time putting a 2500-word (typical article length) explanation into every library I write? If you do, I cannot help you because I refuse to spend my time stating the obvious.
I've never put anyone on the ignore list, and I'm not going to start with you -- though I do ignore some people. This is a public forum, and when I choose to help, it is my hope that what I post helps many more than the person who started a particular thread.
Hi potatohead,
thank you for answering. Commenting the why and/or purpose makes sense to me.
Bean I agree. Live by the library and die by the library. Or to become completely independent create you own hardware-chip from scratch.
To me still just a gradual difference. Although I readily admit that there are many degrees from end to end.
best regards
Stefan
Then, potentially share them, and or expand on it all for others. An example is in my signature for the colors in the Parallax reference graphics driver / demo.
People are going to write the comments they write. I'll take 'em. If I end up writing new ones, share that, and everybody benefits.
Maybe over time that activity results in improved comments.
For me, this is my process on any new code:
I'll first run it, check to see that it builds, whatever. If that's possible.
If it's a snippet, I'll check it in it's original context, if that's possible.
Then read it, parsing for intent as shown. When I can get to a running commentary as shown above, I'm probably well on my way to understanding that code well enough for it to be useful. And I probably learned something new in there too.
Integrate with my work, comment, continue.
Share, if appropriate.
Yes. You never ever stop learning. Tech changes, code changes, and so forth.
The most important skill is understanding how to better and more quickly arrive at an understanding for the task at hand.
Each one commented, understood and use adds to skill, and you get quicker and better.
What you described is a good idea. Will try do so.
best regards
Stefan
I took a coupla minutes to think through what it could be doing, then started the commentary.
The trick I like is to get it to flow in words nicely and with fewer words too. When you use a lot of words on a line, you've not yet boiled it down to something one PASM instruction can generally do. Use more lines, or fewer words! Both help sort out flow and data to make an effective program.
That process seems to mirror how the program itself flows and I get it by inference and often deduction.
When I have been away from it, like I am right now, doing this also helps to bring back that mental context needed to do this stuff. There seems to be a short term memory gap in play when task switching, or just ramping up to do something. This kind of review seems to populate that "cache" and it makes operating with the tools and the problem easier as there are much fewer "lookups" to perform. In computer terms, swap out the garbage, swap in the library code...
While it may seem time consuming, the improved flow I get tends to make or help me program better, which generally saves a lot of other little bits of time, moat notably the time spent flipping between references, etc... Looking up an instruction, then writing it, then thinking about the next step, then trying to visualize it, then looking up another one sucks... Takes all day.
Reviewing code you wrote last, or library code, or a snippet, seems to fill in the instructions and a lot of details. That's faster right there. Building up a running list of small, instruction sized tasks in plain language seems to fill in a lot of the intent and steps. Populating easy ones speeds it all up and improves too:
And that is generally pseudocode.
Write what needs to happen, then write it again using simpler and still connected ideas.
Soon, the pseudocode and whatever diagrams and notes that result look a whole lot like the kind of useful comments we've got in the discussion here.
Then, just write a PASM instruction or two for each line.
I may spend more time resolving the problem this way than I do writing PASM instructions, but those also seem much closer to doing what I want too, which helps with debug and generally just putting the appropriate instructions in the right order types of tasks...
I will also just start filling in instructions, once the plain language gets simple enough. Populate simple mov, rdbyte, jmp, etc... and slowly it will come together, making the real hard ones that do the meaningful work more obvious.
This is like a puzzle, where it's hard at first, but as more and more of the pieces are connected and the picture intent is known, fitting the harder ones takes less effort because the obvious problem space associated with them is smaller, allowing for one to consider far fewer opportunities while also making them better, easier to see or guess ones.
For a video example, maybe it goes like this:
Display text screen:
Characters are 1x8 bytes
There is a font in HUB RAM
Display all characters on a line
Display them from upper left to lower right
Display all of them
Do it every frame.
Now, break it down.
For each scan line: (for example)
1. Read the character value from the HUB to know which one to display.
2. Note the scan line and use that as a hint as to which byte in the character needs to be displayed.
3. Fetch that byte from the HUB
4. Put it into the waitvid.
5. Do all the chars for that line.
6. Do all the lines for the screen.
7. Reset it all and do it again for each frame.
And further:
need to know scan_line, font_start_address, video_buffer_address, num_of_waitvids, line_offset, etc...
Beginning of line
1. Prepare to read character number from hub
2. prepare pointer to font in hub memory
3. read character from hub
4. calculate font address based on character number
5. add scan line offset
6. get byte from the right character
7. stuff it into the waitvid
8. done, next character!
9. done, next line!
10. done, next frame!
And further might be something like:
etc....
Soon, it's just filling in the blanks, and it goes fairly well.
This may work well if you do well with words. Maybe not so well, if not. And in that case, pictures, or whatever works might make more sense.
In any case, that's my general process, be it my own code, library, or something I'm doing PASM on. Or anything really. If it's a new language, then I do this A LOT. Until I find I can write simple things without doing it.
If it's code somebody else wrote, the instruction blanks are filled, but you need the intent blanks filled in! That's what the running commentary process accomplishes.
If it's code you are writing, you need to figure out what to write, which is the intent blanks. Once that's done, you work down to fill instruction blanks in.
If it's code you are combining, however it goes, then you need to know the intent, and map out the data flows and write the words that get the data where it needs to go and do what it needs to do.
If it's math, solve it however you can solve it and make a few test cases so you can check what the P1 is going to do.
Then use factoring, algebra and whatever other math options you can find to use P1 operations, but simpler ones. Make sure the tests pass. You may want a subroutine, like for divide.
Get down to add, shift (multiply by power of 2), subtract, and so forth. Make sure the tests pass.
Say you've gotta plot a dot, or calculate an address.
In the case of the dot, the address of the byte where the dot lives is a nice calculation to work with. Say the screen is one byte per pixel, and it's a 160x96 screen.
Given X and Y, the dot address is = (y*160)+x
A multiply by 2 and add is what we got. So use closest power of 2 and add more
dot address = (y*128)+(y*32)+x
Our checks need to be to make sure X and Y do not exceed their values.
y 0 - 95 and x 0 - 159
Some tests:
x 0 y 0 = 0 = beginning of screen
x 50 y 40 = (6400)+(50) = 6450
x 159 y 95 = (15200)+159 = 15350 = end of screen.
Edit: should add edge cases:
x159 y 0
x 0 y 95
etc...
words might be:
skip range checks (because this is just example)
prepare to compute dot or pixel address
first do y
add x to get dot address
call the pixel plotter to see it on screen
code might be:
I had a bug in the above, because I wrote "add address, pixel_y" and when I reread my comments, saw it. The other one was I added "temp" which should have been "address", both corrected in the above. That's nice when it happens.
And there is at least one simplification there too. Really don't need to zero out the address variable as it's going to get written over to do the two part Y address calculation. So that can go.
Result is a nice code snippet that's very likely to do what it is supposed to. Then code it, or insert it and carry on, no different from the library example above.
I just did these on the fly, no Prop Tool, IDE, etc... But now, I'm ready to fire up a board and do some stuff! Most of that mental context is back.
(Goes off to play on P1 for a while now)
I can not attach the propeller image here,
so sent it to you in private.
Admit that you are a failure Jon! and look! IF ONLY you commented it properly then others could make it FASTER AND MORE RESPONSIVE !!!!! Yes, I think I will have a good laugh with you too.
Anyone who needs verbose commenting is not normally in a position to really even just understand the code, maybe they might understand the comments, but you need to understand why the code is written the way it is to achieve it's grand purpose in order to "tweak" it. If you have this level of understanding it is extremely unlikely that you even need someone else's code let alone comments, especially verbose comments in the first place.
@Stephan, btw I have to say that reading these sensors, accepting serial commands, and logging onto an SD card is a snap in Tachyon. But there would be no real challenge if you did it that way as everything is too easy and MJB has the 1-wire search code too.
My mistake (along with my apparently-crappy commenting style). I use "scanning" to mean reading known devices. One "searches" the 1-Wire buss for unknown devices, catalogs them, then scans later.
About code comments:
I've found that unless you understand what the code is for then no amount of comments will help you understand it. Similarly, I've found that if you know what the code is for then comments aren't so necessary.
However, it helps to add comments when you do something not so straight forward. These types of comments are very helpful months down the road.
Also, good variable and function names go a long way too.
I recommend reading the 1-Wire spec.
And hey, comments are comments! I'll take 'em. Almost always better than no comments at all. Same with code. I'll take it. Almost always a good thing too.
@Kye: Deffo. When it's a non-standard, or trick use, those comments are gold. Give that code a year, and most people who wrote it and didn't comment, will look at it and have to figure out the trick again...
And this:
Yes! I'm so guilty of using a few letters, older school register style. A,X,Y, and so forth. When I go back to that code, the comments are probably what makes it somewhat easy. Where I didn't do that, it sucks. Gotta parse it again.
But, I hate the typing... Ah well.
@StephenL38: You should reconsider tossing ignore out there so quick. A little bit of charm, or humility, or just "thanks man, nice catch!" kind of thing goes a really long way. Reconsider when you sell yourself short. Working with the people pays as well as working with code does.
If my commentary seemed long, or elementary, etc... it's just to better associate the words in what are effective comments in my experience to instructions / code. And it's for other passers by who may benefit. Don't think it's aimed at anyone in particular. Just thought it would have some value.
And besides, it did get me propping tonight, which is never a bad thing.
Indeed. I've learned a ton by reviewing code written by others against an official data sheet. Often, the data sheet will provide insights that will help us discover why a programmer made one choice or another.
On board with Kye there, too. I tend to be concise, yet use meaningful names. A young programmer once told me I should change the name of the out() method in a 74xx595 object to output_one_byte_with_74xx595(). After I picked myself up off the floor, I said, "No, thank you." and I suggested that with experience, his method names would become more practical.
I think the real key is to dive in and do it. Personally, I tend to write libraries instead of looking for them because I enjoy programming -- and when it comes to code with my name on it I tend to be a control freak. My acting teacher used to say that actors have to get on a stage or in front of a camera to advance in their craft. Watching good acting is not enough -- otherwise there would be no teachers, we'd simple watch great plays an movies. I think programming is the same: we have to write code, not simply stitch together objects written by others. Again, I'm not anti-object, in fact, I often chastise my friend Rick for not asking for my code. To his great credit, he wants to try first. When he cannot get where he wants to go he often invites me to lunch or dinner and we talk. If things get desperate, he'll ask for a bit of code. He's made a lot of progress the last couple years, and his work was featured in the Bud Light Super Bowl commercial. Rick helped build and did the electronics for the human-sized Pac Man ghosts. He used my WS2812 driver because that's beyond him at the moment, but everything else -- with just some enthusiast cheer-leading from me -- was all him.
86 AA 'load ACCA with immediate byte $AA
BD F6 4E ' jump to the sub to clear the display and home the cursor
BD F7 AD ' jump to the sub to write the contents of ACCA to the current cursor position on the display
While I learned how to do it the hard way, I also picked up some bad habits in that most of my programs weren't commented or even really written down.
Along about 1986 or so, I bought a PC that didn't have a hard disk drive (was still a couple years out) but I was able to write my robot programs in mnemonics instead of byte codes. And comment them. I could hit the compile button and then use the dot-matrix printout for a list of bytes to manually enter into the robot.
Every tiny change in any program resulted in me having to manually count address offsets (all of them) throughout.
Stuff today? You youngsters have it WAYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY easier than I ever did. My first PC cost nearly $4000 by the time I left the store. That is $4000 in then-Dollars, which is probably like $8000 today.
384K of RAM and one 5.25", 360K single-sided drive.
This isn't intended to be a rant about who walked through the most snow to get to school, it is intended to let you know that the world expects you to do your own heavy lifting.
You will be better off for your efforts.
I have seen the term "script kiddies" bandied about.
http://forums.parallax.com/showthread.php/141061-TACHYON-O-S-Fast-Forthwrite-n-Furiously-Interactive-n-Compact-FAT32-Networking?p=1316539&viewfull=1#post1316539
But I have nothing to say or to ask at the moment....
There seems to be no resonance on what I was asking for.
So I decided to stop trying to create resonance or trying to explain
why it makes sense to me to do it this or that way.
@potatohead: Thank you for explaining on how you do it.
Anything that is provided will need to be reworked to fit your programming style, and that means analysis.
Automatically (and reliably) inventorying a 1W buss is a tricky proposition, and if you are going to venture into those waters, you need to bone up. To my way of thinking, providing you with more than just the very basics will hurt you more than help you.
Again, I'm not trying to be a jerk, but that is how I personally read it.
I hope you find that which you seek. I did some 1W stuff with PICs but never the Propeller.
It runs entirely in Spin, searches the bus for any connected devices and stores the rom codes, reads temperatures, and searches for alarms. Works with externally or parasitically-powered devices.