Home
JAQForum Ver 24.01
Log In or Join  
Active Topics
Local Time 04:21 27 Nov 2024 Privacy Policy
Jump to

Notice. New forum software under development. It's going to miss a few functions and look a bit ugly for a while, but I'm working on it full time now as the old forum was too unstable. Couple days, all good. If you notice any issues, please contact me.

Forum Index : Microcontroller and PC projects : (MM) D/A converter

     Page 2 of 3    
Author Message
MicroBlocks

Guru

Joined: 12/05/2012
Location: Thailand
Posts: 2209
Posted: 08:06am 07 Jan 2013
Copy link to clipboard 
Print this post

Well, it does what it does. :)
I think the real challenge comes later when the SPI is used.
Not that sending data to the SPI will be difficult but the timing.
The timing if it is critical will change everything. And indeed the lot more work is in that.

I like KISS but if i was in teaching mode i would give this code a very low grade. :)

Using EOF is in my opinion so easy to use that not using it is a shame.
Code should be as error free as possible and EOF will prevent an error to occur.
This will be very useful when it is time to expand on your program as it will prevent new and unexpected behavior.

I don't know what is the most interesting part for you when using MCU's.
I get the most fun out of making code that is as small as possible and as robust as possible. I go through great lengths, like pulling out cables, inputting text when numbers are expected, pressing all the wrong buttons etc to get the software to crash. For that reason i concentrate the most on software and it is also the reason for responding to your post as it is more about software then hardware.

If however you get the most joy out of hardware, soldering, interfacing etc and software is just a necessity, then you probably want to do the job in software as quickly as possible and not worry about best practices and robustness. In that case ignore the above and have fun, because that is the most important.

If timing is important you can check how close you are to the target by using the TIMER command and function.
Firsdt you use TIMER = 0 to reset it. Then after a specific number print the timer value on the screen.
If you want to have 50 per second you could use a counter variable to keep track of how many times the code in the loop has run.
You should get timer value 1000 when it exactly 20ms per message but in practice it will deviate.
If you want to do that you will need to add a variable before the DO statement:

Count = 0
TIMER = 0

then right after the PAUSE 20 statement:

Count = Count + 1
If Count >= 50 then
Count = 0
Print Timer
Timer = 0
end if

I am curious what kind of values you will get and how close to the 1000 they are.
Edited by TZAdvantage 2013-01-08
Microblocks. Build with logic.
 
Talbit
Senior Member

Joined: 07/06/2011
Location: Australia
Posts: 210
Posted: 12:13pm 07 Jan 2013
Copy link to clipboard 
Print this post

Thanks Jean,
And thanks for your continued input.
I'm not the world's best programmer ("a very low grade" is acceptable!) so taking things in small bits is the best way for me. Input from forum members has been a real lifesaver. I did BASIC at tech 100 years ago and haven't done much since although I did cut my teeth on the RCA 1802 chip. We made some data loggers for a research project. It had 16 X 16 bit registers and you needed every one of them! So working at bit level is what I like best. The MM has me inspired again.
You've probably seen my other posts on my clock. I started it to get others to get stuck into me and come up with something better. No one has yet. This Apollo 11 data is something I'm just dabbling with. According to my rough calculations, the amount of data that I have amounts to about 13 hours of the first moonwalk. Don't worry. I've followed everyone's comments on the EOF and the timing. I just want to get it going first and then refine things later. I will go through each data item on the PC and tidy it up by making sure that each item is valid and is not a random number. In fact there are a lot of those. There are data dropouts, random numbers and what would be described as glitches in the data. It's not surprising. After all, the data did come all the way from the moon, through God only knows what path. Then when I'm happy I'll copy it onto the SD card. Then I'll add error catching in my program to check each item as it's read off the SD card, then SPI it. I'll probably replace it with the number that was previous to the error. If I don't do this then the Helicorder pen will show a twitch or at worse slam to the side for a brief moment.
When I say that timing is critical in seismic work - it's important that each seismic station is locked into UTC. Some scientists insist on uSec accuracy. But for this project it's not all that important. A few mSec either way is not an issue. I just need to make sure that at the end on the 13 hours I'm not minutes out. I have the original seismogram to test it by. It has the Helicorder time marks on it. The digital data is time tagged but Yosio warned that it can't be relied on because of the way it was resurrected. In fact I can see that there are say 10 readings in a group then there might be 11 or 9. But I'll take your advice and check the timing. If I wanted to be really accurate I could use the PPS from a GPS. Over a 13 hour period it in fact might be essential!
I wish these damn boards would arrive.
Anyway, please keep the advice coming.
Trevor
Talbit
 
MicroBlocks

Guru

Joined: 12/05/2012
Location: Thailand
Posts: 2209
Posted: 07:28pm 07 Jan 2013
Copy link to clipboard 
Print this post

A PPS is i think not necessary to be accurate.
MMBasic has a timer interrupt that is accurate within 0.1ms.
I think that is all that is necessary, if testing shows that this timer interrupt is not really accurate you can use one of the PWM pins to generate the 20ms pulses.
Those will be generated by the internal PIC32 peripheral and are very accurate.
By connecting a PWM pin output to another pin for input you can use the interrupt of that input pin to provide very accurate timing to the MMBasic program.
Response time is again around 0.1ms because that is the time for the basic interpreter to process that interrupt.
The next pulse will be exactly 20ms later, effectively removing the possible timing inaccuracy of MMBasic.
The routine that handles the interrupt has to be shorter then 20ms, more like 15ms to prevent missing a 20ms pulse.

Edited by TZAdvantage 2013-01-09
Microblocks. Build with logic.
 
Talbit
Senior Member

Joined: 07/06/2011
Location: Australia
Posts: 210
Posted: 12:31am 08 Jan 2013
Copy link to clipboard 
Print this post

Using the counter and the timer it works out to 1001/1002 milliseconds per 50 samples, with a pause of 18. A quick calculation says that after 13 hours I'll be about 46 seconds out.

OPEN "ApolloAS.txt" FOR INPUT AS #1
Count = 0
TIMER = 0
x = 0
DO
LINE INPUT #1, values$
PRINT values$
Pin(14)=0
a = SPI(12,13,15,val(values$),H,3,12)
Pin(14)=1
PAUSE 18
Count = Count + 1
If Count >= 50 then
Count = 0
Print " "Timer
x = x+1
Print " "x
Timer = 0
Endif
LOOP

I've also got a software counter that gives me a count every 50 samples, i.e once a second. I'm up to about 1.7 hours and it is running okay.
BTW, I've reverted to the three original characters ascii data which hovers around 530.
I need to add the control bits to this to make up the 16 bit binary word for the SPI.
Tomorrow I'll connect a cro and see if there is anything actually beng sent from the SPI tx pin.
TrevorEdited by Talbit 2013-01-09
Talbit
 
MicroBlocks

Guru

Joined: 12/05/2012
Location: Thailand
Posts: 2209
Posted: 04:31am 08 Jan 2013
Copy link to clipboard 
Print this post

That is a pretty good result!
1001/1002 is perfect.
The next thing you could test for is exceptions.

If Count >= 50 then
Count = 0
if Timer > 1005 then
x = x+1
print " "Timer" "x
Timer = 0
end if
end if

If you run it with this it will only print when the time spend in the loop is too long.
Change the value 1005 for a maximum value that the timing is allowed to drift.
Reading speed from files on the SD can vary. This can cause (worst case) delays of a few seconds. When that happens the timing is completely off and another way of processing have to be made..
Running the above for the whole file will detect when the processing is too slow.
If you process the whole file and no timing drifting is detected in trial runs then you are good to go.

Microblocks. Build with logic.
 
Talbit
Senior Member

Joined: 07/06/2011
Location: Australia
Posts: 210
Posted: 08:43pm 15 Jan 2013
Copy link to clipboard 
Print this post

Okay, almost there!
Can anyone help me with this? It's probably mentioned somewhere down in the archives but this is related to my project. It's binary arithmetic so I know someone will answer straight away!
The SPI command sends the MSB first. See Appendix D
The data for the SPI chip on the Futurlec DAC board (Microchip MCP4922) says it wants the LSB first.
So, say my 16 bit binary number is (LSB)0100110001101110(MSB), how do I turn it around so I get 0111011000110010
The DAC boards from Futurlec still haven't arrived. I contacted them and they said they have just been posted. Yeah Right! I think they forgot.
Regards
Trevor
Talbit
 
ajkw
Senior Member

Joined: 29/06/2011
Location: Australia
Posts: 290
Posted: 10:04pm 15 Jan 2013
Copy link to clipboard 
Print this post


there may be a better way but try


byte = 19566 ' sample 0100110001101110

for i = 15 to 0 step -1
newbyte = newbyte + ((2^(15-i)) * ((byte AND (2 ^ i)) > 0))
next i

print newbyte ' Should return 30258 being 0111011000110010


In other words, test the MSB and set it in a new var as the LSB and step thru. QED.



Sample code only, make sure you do your own error testing and that it suits your purpose!
 
MicroBlocks

Guru

Joined: 12/05/2012
Location: Thailand
Posts: 2209
Posted: 10:12pm 15 Jan 2013
Copy link to clipboard 
Print this post

Talbit,
The datasheet from the MCP4922 clearly shows that the data is to be send MSB first!
Look on page 7 and 25 from this datasheet: http://ww1.microchip.com/downloads/en/DeviceDoc/22250A.pdf

Where did you find the information that it should be LSB?

Microblocks. Build with logic.
 
ajkw
Senior Member

Joined: 29/06/2011
Location: Australia
Posts: 290
Posted: 10:36pm 15 Jan 2013
Copy link to clipboard 
Print this post

Refer my previous post in this thread.

Thanks to crackerjack for the bit test in the BIN8.bas code in the sample library. A better test than I had done in the past.

There are also a number of other bit manipulation functions in BIN8.bas
 
MicroBlocks

Guru

Joined: 12/05/2012
Location: Thailand
Posts: 2209
Posted: 10:46pm 15 Jan 2013
Copy link to clipboard 
Print this post

Talbit,

I just noticed this in your post:
(LSB)0100110001101110(MSB)

The LSB and MSB should be switched like this as it is the normal practice and how values are stored in memory:
(MSB)0100110001101110(LSB)

The bits are D15, D14, D14 ....... D3, D2, D1, D0


It works the same as with our normal decimal system:
123
Here the 1 is Most Significant as it stands for 100, and the 3 Least Significant.

Microblocks. Build with logic.
 
Talbit
Senior Member

Joined: 07/06/2011
Location: Australia
Posts: 210
Posted: 12:44am 16 Jan 2013
Copy link to clipboard 
Print this post

Gents,
This would have to be the most embarrassing day of my life! You're absolutely right. The MSB is first. The data sheet even shows the 1st. clock "0" associated with D15, the MSB. My blunder.
Thanks anyway to ajkw for the interesting number crunch on how to turn it around.
Jean, I was trying to indicate that the MSB would normally come first hence I put it to the right. Not good!
So my data should be D15, D14, D13 ....... D3, D2, D1, D0 0111011000110010
The 0111 are the control bits and the rest is the data.
I was working off a 2004 data sheet (DS21897A). I don't know where it came from. Probably a link on the Futurlec site. But it's no excuse. Thanks for pointing me to the newer data. It shows a bit more than the older sheet.
Thanks again.
Trevor

ps
I won't post my final code until I get it working.
TrevorEdited by Talbit 2013-01-17
Talbit
 
James_From_Canb

Senior Member

Joined: 19/06/2011
Location: Australia
Posts: 265
Posted: 01:09pm 16 Jan 2013
Copy link to clipboard 
Print this post

Just in case anyone wants to swap two bytes in a 16 bit word, here's some code. It shows how useful the AND and OR functions are for manipulating bits. This'll be old news to experienced programmers, but there might be some of you out there who are interested.

James

' Example code to swap two 8 bit bytes in a 16 bit word.

byte = 19566 ' sample 0100 1100 0110 1110

print "Start word is " bin$(byte)
print

' First, split the 16 bit word into two 8 bit bytes, Left byte and a Right byte.
' Use the AND function to extract the bits we want. They're already on the RHS of the word.
ByteR = byte AND &b0000000011111111 ' should return 110 decimal being 0000 0000 0110 1110
print "Right byte is " bin$(ByteR)
print

' Then extract the leftmost 8 bits using an AND mask and SHIFT the bits to move them to the RHS
ByteL = byte AND &b1111111100000000 ' should return 0100 1100 0000 0000
ByteL = ByteL / &b100000000 ' shift right by 8 bits. Should return 76 decimal being 0000 0000 0100 1100
print "Left byte is " bin$(ByteL)
print

'Now swap the two bytes. The original Left byte has already been moved to the right of the 16 bit word. Leave it there.
newbyte = ByteL ' newbyte should be 0000 0000 0100 1100

'The original Right byte has to be moved left. Do this by shifting left 8 times (multiply by 2^8, or 128)
TempByte = ByteR * &b100000000 ' Should return 28,160 decimal being 0110 1110 0000 0000
print "Temp Byte is " bin$(TempByte)
print

' now merge the two bytes back together again using the OR function
newbyte = newbyte OR TempByte ' Should return 28,236 decimal being 0110 1110 0100 1100
print "New word is " bin$(newbyte)
print "The two bytes have been swapped."

My mind is aglow with whirling, transient nodes of thought careening through a cosmic vapor of invention.

Hedley Lamarr, Blazing Saddles (1974)
 
Talbit
Senior Member

Joined: 07/06/2011
Location: Australia
Posts: 210
Posted: 12:45pm 17 Jan 2013
Copy link to clipboard 
Print this post

Thanks James. I could use that on other projects later.
I'm wondering if it might be useful to start a thread on this subject. Someone might have already started one but it might have disappeared into the ether if people don't keep adding to it and keeping it active.

For now, I have a question on how the picking of the data off the SD card works.
My code is this and it works perfectly...

'Simplified code. The data is on the SD card.
OPEN "Apollo.txt" for INPUT AS #1
DO
LINE INPUT #1, values$ 'Get the first DATA from the SD card
'Crunch the numbers.
LOOP 'Go and get the next DATA from the SD card

My question is, how does it know to get the next line of data. Is the #1 a pointer that increments?
I like to know exactly what’s going on so I don't come unstuck later if I assume too much!
Regards
Trevor
Edited by Talbit 2013-01-18
Talbit
 
James_From_Canb

Senior Member

Joined: 19/06/2011
Location: Australia
Posts: 265
Posted: 01:41pm 17 Jan 2013
Copy link to clipboard 
Print this post

When you open a file MMBasic will set up some data fields to manage it. You don't get access to the fields directly. One of those management fields will be a pointer that keeps track of the next byte to be read from the file.

The number after the hash doesn't increment as you read through a file. If it did, you'd be pointing to the next file you have open (assuming you open your files using sequential numbers). #1 is just a string telling MMBasic that we're using a particular file and that the associated file management fields should be used.

When you tell MMBasic to do a Line Input, MMBasic reads all the bytes from the next pointer up to the End of Line characters. The next pointer is then changed to point to the byte after the EOL character/s.

The question everyone asks sooner or later is how the program knows when the End Of File (EOF) has been reached. If MMBasic has only read bytes preceding the read pointer (which points to the next byte to be read) then how can it know that the last byte in the file has been read? That's up to the Geoff, but probably involved reading a byte ahead to check for the EOF character, while not changing the read pointer. It doesn't really matter how it's implemented. Just trust that it works. Except in one case...

MMBasic only handles text files so far. It doesn't handle binary files. If you're reading a binary file using MMBasic's text file functions you can have your read terminated by an EOF character. Binary files are likely to have data bytes with a value of 26 which is interpreted by MMBasic as an EOF character. This stops the entire file being processed.

I hope that made some sense. Ask if it didn't.

You should get an error when your code (above) tries to read past the End of File. You need to use the EOF() function. Geoff's manual says EOF(#nbr) "Will return true if the file previously opened for INPUT with the file number "nbr" is positioned at the end of the file" so try replacing the DO with DO While NOT EOF(1).

HTH

James

My mind is aglow with whirling, transient nodes of thought careening through a cosmic vapor of invention.

Hedley Lamarr, Blazing Saddles (1974)
 
Talbit
Senior Member

Joined: 07/06/2011
Location: Australia
Posts: 210
Posted: 04:03pm 17 Jan 2013
Copy link to clipboard 
Print this post

James,
That all makes sense. Thanks for the input.
My numbers on the SD card aren't HEX like at the beginning of this thread. They are just 3 digit numbers. I do a bit of bit bashing to get what I want. I'll post it all when it's all working (to save embarrasment). I have inserted my own EOF. I've just inserted the number 1050 at the end of the 11.5MBYTE file and check for it each line read. All of my numbers are less than 1050 so it doesn't exit early. When it reaches 1050 it exits the SD card read routine and stops. It seems to work okay.
Chrickey Futurlec are slow! I wanted to get this finished before I went back to work on Monday.
Regards
Trevor
Talbit
 
paceman
Guru

Joined: 07/10/2011
Location: Australia
Posts: 1329
Posted: 04:12pm 17 Jan 2013
Copy link to clipboard 
Print this post

  Talbit said   Thanks James. I could use that on other projects later.
I'm wondering if it might be useful to start a thread on this subject. Someone might have already started one but it might have disappeared into the ether if people don't keep adding to it and keeping it active.
Trevor


I was thinking the same thing Trevor. This info re binary manipulation, MSB/LSB transmitting and file reading is very good info for we "ordinary" folk Unfortunately it'll be difficult to find later under a thread on D/A converters!

Maybe Glenn could put it in a separate thread under "SPI bit transmission & file reading" or some such. A good start point would be your post (Talbit) just after 4pm on the 16th Jan. I've already copied James' little swapping program/info into a folder I keep for useful MMBasic stuff.

Greg
 
James_From_Canb

Senior Member

Joined: 19/06/2011
Location: Australia
Posts: 265
Posted: 06:43pm 17 Jan 2013
Copy link to clipboard 
Print this post

I agree with the idea. You don't need Glenn to solve it though. There's nothing stopping you cutting and pasting the relevant information into a single post and starting a new thread with an appropriate title. Even better, as new threads expand on the subject people could update/improve the summary.

If you do, I'd suggest that you preface the thread's title with SUMMARY: so that users can use the search facility and only search for the threads with SUMMARY in the title. The default is to search for the keywords in the message body, so a search for SUMMARY would find this posting.

Just a thought.

James
My mind is aglow with whirling, transient nodes of thought careening through a cosmic vapor of invention.

Hedley Lamarr, Blazing Saddles (1974)
 
Gizmo

Admin Group

Joined: 05/06/2004
Location: Australia
Posts: 5078
Posted: 07:48pm 17 Jan 2013
Copy link to clipboard 
Print this post

Some sort of index is needed. The forum does have search facilities, but you got to know what your searching for. But an index of topics, like A-D conversion, File handling, etc, and under each topic a few links to relevant posts.

If someone where to put together and manage the index, I would be happy to put it on the forum as a sticky, so its always at the top.

Glenn
The best time to plant a tree was twenty years ago, the second best time is right now.
JAQ
 
paceman
Guru

Joined: 07/10/2011
Location: Australia
Posts: 1329
Posted: 09:26pm 17 Jan 2013
Copy link to clipboard 
Print this post


I had a quick look at the forum "Search" functions using "summary" as the input. If you select to search on the body of the posts you get too many hits. Also it's difficult to know what the "found" posts are about, so you have to look at each in turn which is too time consuming. If you select to search on the titles there are currently no hits at all.

I think a combination is needed. If Glenn put a "sticky" post at the top of the forum which said to search for "summary" in the "titles" area (not the default body area) for information on particular subjects, then a manageable list of "Summary" threads would come up (currently there wouldn't be any!). The sticky should then say to search the body of the most likely summary thread, using the keyword(s) of interest. A few lines of suggested keywords could be included in the "sticky" which would be easy to update.
what do you think?

Greg
 
Talbit
Senior Member

Joined: 07/06/2011
Location: Australia
Posts: 210
Posted: 08:29pm 25 Jan 2013
Copy link to clipboard 
Print this post

The DAC boards from Futurlec finally arrived and it works beautifully. The Apollo 11 moonwalk seismic is being faithfully reproduced on a Teledyne Geotech Helicorder. The whole data set should last about 14 hours. Further work needs to be done to get the time marks in the exact spot to match the original recorded on the day of the big event in 1969
When I've completed a full run I'll try and take a happy snap of the setup, the seismogram and the circuit. The circuit is pretty straight forward.
Here's the code. All pretty straight forward when you know what to do!
Thanks to all who contributed with advise and suggestions.

Whoops - In the code where it says 'Add DAC control bits (0111) resulting...
that should read 0001

'Apollo 11 First Lunar Seismogram, July 1969
'Original data supplied by Yosio Nakamura Institute for Geophysics
'University of Texas at Austin [yosio@utig.ig.utexas.edu]
'Stored on Maximite SD card
'Trevor Dalziell 26 January 2013
'
'Data to the Futurlec SPI DAC board (Microchip MCP4922) is 16 bit
'straight binary.
'Only 1 of the DAC amplifiers is used
'Bits 0-11 are data from the Maximite.
'Bit 12 is Output Power Down Control bit (active low). Set to 1
'Bit 13 is Output Gain Select bit. Set to 0. Gain of 2.
'Bit 14 Vref Input Buffer Control. Set to 0. External Vref.
'Bit 15 selects which DAC to write to. Set to 0. Writes to DAC "A"
'This relates to the upper four bits as 0001

'____ SPI Setup ____

Pin(14) = 1 'Pin 14 is High
Pin(15) = 1 'Pin 15 is High
Pin(16) = 1 'Pin 16 is High
Setpin 12,2 'Digital input - Data Rx (Ignored)
Setpin 13,8 'Digital output - Data Tx
Setpin 14,8 'Digital output - DAC Chip Enable - Active low
Setpin 15,8 'Digital output - Clock - Active low
Setpin 16,8 'Digital output - LDAC - Active low

OPEN "Apollo.txt" FOR INPUT AS #1 'This file should have 1050
'as the last data entry (EOF)
DO

LINE INPUT #1, values$ 'Get the first number from the SD card

a = VAL(values$)

IF a = 1050 THEN '1050 = EOF
EXIT 'Exit out of loop if EOF
ENDIF 'Not EOF so continue

Seismic = a AND &B111111111111 'Mask the data to prevent overflow
Seismic = Seismic OR &B0001000000000000 'Add DAC control bits (0111) resulting
'in a 16 bit word

'Now send the data via SPI
PIN(14)=0 'Enable DAC
s = SPI(12,13,15,Seismic,H,3,16) 'High speed, Mode 3, 16 bit control and data.
PIN(14)=1 'Disable DAC
Pin(16)=0 'Latch the data
Pin(16)=1

PAUSE 20 'Wait for 20 msec

LOOP 'Go back and get the next number

CLOSE #1 'EOF found so stop reading the SD card data


'Now just output a voltage that will keep the pen centred


'&B001000010010 Helicorder pen centre position?

PIN(14)=0
s = SPI(12,13,15,&B0001001000010010,H,3,16) 'High speed, Mode 3, 16 bit Control and Data.
PIN(14)=1
Pin(16)=0 'Latch the data
PAUSE 1
Pin(16)=1
END
Edited by Talbit 2013-01-27
Talbit
 
     Page 2 of 3    
Print this page
© JAQ Software 2024