Experimenting with A/D modes in TAQOZ - help me!
Peter Jakacki
Posts: 10,193
As much as I wanted to experiment with A/D and D/A I just haven't had time. But I decided to do a one liner in TAQOZ and although it is a bit basic, it seems to do the job:
Now I set the pin to 1V, read, adjust and save that value (the long way)
With this manual calibration I take readings for 1V 2.75V 3.3V and 0.25V
pub ADC ( cycles -- ) F %100_011_0000000_00_01111 WRFNC WXPIN 0 WYPIN L ;So if I select a pin such as 40 PIN I can then say 40000 ADC to setup pin 40. I haven't done any auto calibration yet since I have to delve through the documentation but I just setup an array for all the pins to store a min reading for 0V and a reference reading for 1V, but mind you this is only just for mucking about.
64 words amin 64 words arefThen I create a couple of words to reference those arrays using the current pin and create a VOLTS@ word which will read 1,000 for 1V in, and 3,000 for 3V in etc.
: AREF @PIN 2* aref + ; : AMIN @PIN 2* amin + ; pub SETADC ( min ref -- ) AREF W! AMIN W! ; pub VOLTS@ ( -- volts*1000 ) RDPIN AMIN W@ - 1000 AREF W@ */ ;Now I grab a pin at random and feed 0V into it from my programmable supply, plus I'm using a 10k series resistor just in case.
TAQOZ# 24 PIN 40,000 ADC --- ok TAQOZ# --- ok TAQOZ# RDPIN . --- 6903 okSo I manually set the AMIN or zero ref with this reading.
TAQOZ# 6903 AMIN W! --- ok
Now I set the pin to 1V, read, adjust and save that value (the long way)
TAQOZ# RDPIN . --- 14667 ok TAQOZ# 14667 AMIN W@ - . --- 7764 ok TAQOZ# 7764 AREF W! --- ok
With this manual calibration I take readings for 1V 2.75V 3.3V and 0.25V
TAQOZ# VOLTS@ . --- 999 ok TAQOZ# VOLTS@ . --- 2753 ok TAQOZ# VOLTS@ . --- 3303 ok TAQOZ# VOLTS@ . --- 251 okThat's not too bad I think even if it is rough and ready. But I have only just started so I would welcome any tips for sure.
Comments
To set the pin to 1.85V
It's pretty close, my meter reads 1.88V. Any tips?
In the definition of ADC you use the word WRFNC. What does that do?
Do these definitions require the version 2 TAQOZ or just the v 1.0 rom?
Your efforts are doing a lot to help me understand the smart pins.
Thanks
Tom
With the smartpins there is the basic 5-bit M field to set the mode along with a 2-bit T field for direction control plus all the other bit-fields as we see here: %AAAA_BBBB_FFF_PPPPPPPPPPPPP_TT_MMMMM_0
WRFNC floats the pin (to reset the smartpin), takes the 5+2-bit field and shifts it left one bit then merges it with any other bit-fields that have been set such as filters and low-level pin control, then does a WRPIN after which it will enable it by setting the DIR bit with a L. There are a lot of optional bit-fields for each smartpin so I figured doing it this way could help although I probably choose a better name for the function.
Once I get a handle on these modes I may write a "microphone to VGA" as a one-liner.
All these tests I am doing at present are mainly designed for V2 since this is the version that will need to be ready for the ROM very soon. Of course it may get cut down a lot even after compression, but I'd like to have these extra smartpin modes operating.
Off topic --- One thing I noticed was how you define & use arrays.
When I wrote "Starting Forth" forth I used the following for defining & using arrays:
To store to or fetch from an element: ele# variable_name ! or @ (ele# required for element 0)
That way I didn't have to do the multiply and add to the base variable.
I recall that Tachyon did not have CREATE DOES. Is there a way to do that in TAQOZ?
Thanks
Tom
Standard Forth inlines the dictionary header, link field etc and then a code field pointer followed by the "parameters". TAQOZ of course is very different as it keeps the dictionary header separate (then there is no need for a link field), but there is no code field and parameter field, it just assume by the address that it is assembly/threaded/special.
The code here is very compact: AREF takes 10 bytes but even so I could combine it in such a way with AMIN so the lot takes 14 bytes instead.
BTW, you didn't have to do a multiply but CELLS is one of those ANSI definitions which in our case would be: But 4* in TAQOZ is simply shift left 2 bits anyway. Also, ARRAY assumes you want CELLS, not bytes or words or whatever, so that definition is not very flexible but fairly typical of many PC Forths. It is easy enough to create just the structure we need or not need without any fancy standards.
I've modified my adc program to auto calibrate. It is not a very efficient program (lots of lines & variables) but it works and I think it is pretty clear.
I want to modify it to sample a number of calibrations as well as re-calibrating every few K readings in case there is an effect of temperature rise.
With the pot set to 3.3v I am getting steady reading to 3 digits with variations in digits 4 and 5.
Here's the code.
Of course this code of yours doesn't need the A/D running in another cog since there is no advantage to simply performing a RDPIN whenever you want to read the value in the main printing loop, but I'm guessing you just wanted to play with using another cog.
I stripped out any superfluous comments and moved the delcal code from the printing loop to where it belongs in the task where it obtains and calculates these values. Finally I placed the raw reading and the voltage reading on the same line as it should look cleaner and easier to follow and the printing delay is fixed independent of clkhz if you use V1.1 or V2 (recommended). BTW, putting the 150ms delay at the start of the loop takes care of any task startup and settling delay too so there is no need to have an extra and redundant delays before this.
Hope you don't mind a few tips and you may find that by factoring and simplifying you can reduce unnecessary comments and clutter and make your code more readable, not only for others, but for yourself. Once it is more readable for yourself you will see where you can simplify and improve even more.
BTW - I made it stop when you hit '1' but I'm not sure if that is what you meant since your code did a 1 AND on the returned code so that means that any key that and the lsb set would exit but 0 or 2 or B etc would not.
Also, I will be using the calibration modes myself too, I just like to check the absolute bare basics first to establish a reference. Thanks for trying out the A/D.
Thanks for the critique and explanations. I've made some assumptions about how some word work that were wrong, and I appreciate your help and the time it takes you.
In my versions, I had tried to put the words to start a new cog and run "adcsp" in cog 1 into "adcdata", but I was not able to get it working in a definition. I forgot about cog start up time.
Thanks particularly for your explanations re "why" as well as how, that really helps.
Tom
Yes, that's right, I remember that it does but it was a long day and well after midnight, so I'm glad you picked this one up. After a new TAQOZ cog is loaded and started up it initializes its variables, including the entry in the TASK array which is why we need a delay. But how much of a delay? While 10ms is not a problem for this little demo, it is an awfully long time in other more demanding applications. So I tested it: Turns out that even 10 us would suffice but you could also 2000 WAITX to make it independent of the clock frequency.
So it got me thinking since it is so easy to run NEWCOG that perhaps I could also pass the address of the TASK to it so that extra TAQOZ cogs can be run on-demand. Then I have high level interrupts to look at too.
How about: