First SX Project! - ADC TO PC
A friend of mine needed a cheap device for datalogging sensors in a SharePoint database project. I've been sitting on a couple SX28's for a while, and this was a good project to get me acquainted with SX 2.0. When i jumped into the SX , after years of BS2 I was a bit overwhelmed, but with some help from ya'll at this forum, I was able to wrap my head around it all.
Special Thank to JonnyMac for helping with the Max1270, and Jon Williams for writing all the Serial Comm Routines.
Heres my SX2.0 code, if you can make it better please share with the rest of the class!
Thanks Again Forum!
Special Thank to JonnyMac for helping with the Max1270, and Jon Williams for writing all the Serial Comm Routines.
Heres my SX2.0 code, if you can make it better please share with the rest of the class!
' ------------------------------------------------------------------------- ' Program Description ' ------------------------------------------------------------------------- ' Reads the all channels from a MAX1270 ADC, then spits out a string to a ' PC via a MAX232 Driver. ' ie: *,CH1, CH2, CH3, CH4, CH4, CH5, CH6, CH7, CH8, <repeat> ' ------------------------------------------------------------------------- ' Conditional Compilation Symbols ' ------------------------------------------------------------------------- ' ------------------------------------------------------------------------- ' Device Settings ' ------------------------------------------------------------------------- ID "1270SPIT" DEVICE SX28, OSCxt2, TURBO, STACKX, OPTIONX, BOR42 FREQ 4_000_000 IRC_CAL IRC_4MHZ ' ------------------------------------------------------------------------- ' I/O Pins ' ------------------------------------------------------------------------- SClock PIN RA.0 OUTPUT ' shift clock SIn PIN RA.1 INPUT ' shiftin data Sout PIN RA.2 OUTPUT ' shiftout data CS1270 PIN RA.3 OUTPUT ' max1270 chip select PCin PIN RB.0 INPUT PCout PIN RB.1 OUTPUT ' ------------------------------------------------------------------------- ' Constants ' ------------------------------------------------------------------------- ' ------------------------------------------------------------------------- ' Variables ' ------------------------------------------------------------------------- chan VAR Byte chLevel VAR Word tmpB1 VAR Byte ' work vars tmpB2 VAR Byte tmpB3 VAR Byte tmpB4 VAR Byte tmpW1 VAR Word tmpW2 VAR Word nStr VAR Byte (5) BANK ' for STR and HEXSTR ' ------------------------------------------------------------------------- ' Subroutine / Function / Task Declarations ' ------------------------------------------------------------------------- DELAY_MS SUB 1, 2 ' shell for PAUSE GET_ADC FUNC 2, 1 ' get value from ADC TX_BYTE SUB 1 ' transmit a byte TX_STR SUB 2 ' transmit a string TX_DEC SUB 1, 3 ' tx value in DEC format ' ========================================================================= PROGRAM Start ' ========================================================================= Start: PLP_B = %0000_0000 PLP_C = %0000_0000 CS1270 = 1 ' deselect ADC Main: tx_str "*, " ' send marker char FOR chan = 0 TO 7 chLevel = GET_ADC chan ' get adc tmpW1 = chLevel ** $3880 chLevel = chLevel + tmpW1 ' convert to milivolts tx_dec chlevel, 5 ' send milivolts out tx_str ", " ' send deliminate char delay_ms 100 ' delay makes serial better? WATCH chan, 8, udec ' use Debug --> Run WATCH chLevel, 16, udec BREAK NEXT GOTO Main ' ------------------------------------------------------------------------- ' Subroutine / Function / Task Code ' ------------------------------------------------------------------------- ' Use: DELAY_MS milliseconds ' -- shell for PAUSE SUB DELAY_MS mSecs VAR __WPARAM12 \ SB __PARAMCNT.1 \ CLR mSecs_MSB PAUSE mSecs ENDSUB ' ------------------------------------------------------------------------- ' Use: TX_BYTE aByte SUB TX_BYTE SEROUT PCOUT, T9600, __PARAM1 ENDSUB ' ------------------------------------------------------------------------- ' Use: TX_DEC value {, digits } ' -- transmits "value" in DEC format ' -- "digits" MUST be specified with word values ' -- DEC3 or DEC5 format is used if "digits" not specified or invalid SUB TX_DEC dValue VAR tmpW1 dDigits VAR tmpB1 dIdx VAR tmpB2 dChar VAR __PARAM1 IF __PARAMCNT = 1 THEN ' byte w/o digits dValue = __PARAM1 dDigits = 3 ELSEIF __PARAMCNT = 2 THEN ' byte w/digits dValue = __PARAM1 dDigits = __PARAM2 ELSE ' word w/digits dValue = __WPARAM12 dDigits = __PARAM3 ENDIF IF dDigits = 0 THEN ' validate digits dDigits = 5 ELSEIF dDigits > 5 THEN dDigits = 5 ENDIF STR nStr, dValue ' to decimal string dIdx = 5 - dDigits ' point to first char DO WHILE dIdx < 5 TX_BYTE nStr(dIdx) INC dIdx LOOP ENDSUB ' ------------------------------------------------------------------------- ' Use: TX_STR [noparse][[/noparse]String | Label] ' -- pass embedded string or DATA label SUB TX_STR strAddr VAR tmpW1 sChar VAR __PARAM1 strAddr = __WPARAM12 ' get offset/base DO READINC strAddr, sChar ' read a character IF sChar = 0 THEN EXIT ' if 0, string complete TX_BYTE sChar ' send the byte LOOP ENDSUB ' ------------------------------------------------------------------------- ' Use: aVar = GET_ADC ' -- reads MAX1270 and places value into 'aVar' FUNC GET_ADC adcChan VAR tmpB1 adcResult VAR tmpW1 adcChan = __PARAM1 ' capture channel adcChan = adcChan & %0000_0111 ' limit, 0 - 7 READ Adc_Cfg + adcChan, adcChan ' convert to config bits SClock = 0 ' get ready CS1270 = 0 ' select max1270 SHIFTOUT SOut, SClock, MSBFIRST, adcChan ' send config/channel CS1270 = 1 ' done NOP CS1270 = 0 SHIFTIN Sin, SClock, MSBPRE, adcResult\12 ' get raw adc data CS1270 = 1 ' done RETURN adcResult ' store ENDFUNC ' ========================================================================= ' User Data ' ========================================================================= ' 0 - +5 , channels 1-8 Adc_Cfg: DATA %11110000, %11100000, %11010000, %11000000 DATA %10110000, %10100000, %10010000, %10000000
Thanks Again Forum!
Comments
I've updated your program to 2.00.16 features and improved the TX_DEC routine (I needed it for myself this week).
Slight confusion here.........
I built this project and I seem to be getting 1/2 the full scale output value when I run with a 20 MHz resonator & at 115200 Baud (ADC channel connected to +5VDC).
Went back and installed a 4 MHz resonator and running at 9600 Baud and now I'm getting full scale output.
What am I missing?
Complied w/2.00.18, 2.00.19, & 2.00.20.·Same results with·ALL versions
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
Mike
Post Edited (Mike Cook) : 4/11/2009 7:19:51 PM GMT
I'm using Jon's example as-is posted on 3-14-09.
The problem seems to happen when I compile @ 20Mhz @ ANY baud rate.
Compiled at 4Mhz, max baud rate of 57600 and I DO get full scale output.
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
Mike
Sampling an in line resistor (current measurement) at 10mS, and at 4MHz @ 57600 I'm getting 105 samples per second. Good enough for right now but will need to add an interrupt to dial it in to 10 mS samples per second.
Would like to get the baud rate up to 115200, most of out test equipment operates at this speed. Our programmers give me a funny look when I bring in a piece of “glue hardware” that operates at a different baud rate than that!
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
Mike
Don’t have a resonator, to try, in between 4MHz to 20 MHz.
Seems, to me, like SHIFTIN is dropping the last bit, over 4MHz, just an "un-educated Guess"!
Project built on a Parallax PN: 45301 Proto Board.
Attached the code, Incase I've done something 'Bone Headed'.
Thanks
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
Mike
I have two other MAX1270BCNG chips (got to love www.maxim-ic.com's sampling policy!)
Will try them next to see of there is a difference.
Thanks for the suggestions!
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
Mike
Thanks for the help, hopefully I'm missing something simple.· Might port this to a Propeller to see if I get the same results.
Your example as posted works quite well.
I just need a faster & timed (10mS) output.
Thanks Again,
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
Mike
Post Edited (Mike Cook) : 4/12/2009 10:37:04 AM GMT
As usual you were correct!
Probably not the correct way to fix my problem but changed the GET_ADC function from:
To:
Now this works at 20 MHz @ 115200 baud, but I have to 'fiddle' with the delay loop for 50 MHz, to get the same results.
Next task is to determine how long a NOP is at 20 MHz and put in the proper delay so the function will return the correct value at any MHz other than 4Mhz.
Thanks for the 'bread crumbs' !
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
Mike
for idx = 0 to 11 ' 11 was the smallest delay @ 20MHz
NOP
next
Why not use something like
PAUSEUS 10 ' may need to play with value
Which basically does the same thing (a delay loop) but then you can adjust in microseconds and know that you'll get the same delay even if you move the code or use a different FREQ (i.e. the PAUSEUS will work the same even if you change the project to 50mhz or 8mhz, etc)
P.S. -- NOP always takes 1 cycle -- so at 50mhz it takes 1/50th of a micro second, at 20 mhz, 1/20 of a micro second etc. In your loop, in fact, the instructions that comprise the for/next loop actually take most of the time cycles, not the NOP itself. Again PAUSEUS will give you consistent results (once you decide the correct the delay time) regardless of frequency or device.
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
When the going gets weird, the weird turn pro. -- HST
1uffakind.com/robots/povBitMapBuilder.php
1uffakind.com/robots/resistorLadder.php
Post Edited (Zoot) : 4/14/2009 12:51:10 PM GMT
Thanks for the reply!
Yes that was my idea of determining how long a NOP is at 20MHz, by using PAUSEUS that will save me some reading and math calculations!
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
Mike
PAUSEUS 6
was the answer! Now works properly from 4 to 50Mhz.
Thanks to ALL for the help!
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
Mike