ADC Hex converision questions......
sir_hacksalot
Posts: 15
Hello!
Im havin fun which is the important part!
Anyway.
The ADC0831 code is the heart of my current hack. I have modified it and added buzzers lights relays warnings and an LCD. It pretty cool. Of course I want to apply my new found Voltage monitor to a 12vdc system. I knew Id have to tackle the conversion issue since I will be using 5Vref. So off I went with my 8th grade math skillz, parallax basic stamp forum and google.
The stock code can be found on pages 156 -157 in Stamp works. Please note the $139c value for Cnts2Mv. The comment says that 5000 / 255 = 19.6. Awesome. I don't know Hex from a hole in the wall so I figured all of this was true. Using this information I came up with $1388 for the hex value. Curious, I plugged it in and now my display reads 4980. Hmmmm. Off to study Hex for a few hours......... I stumbled upon some awesome code while perusing the forums from Tracy Allen and hacked it up to help me solve the problem. Here it is...
After hours with various beans and pieces of paper I discovered that If I add 20 to my targetV variable (now MultV) I get the desired output for finding the HEX value.
I have figured out what the Hex conversion for 12v is. I think its $2f10. Why is the question. Why do I have to add 20 to the HEX value to get my targeted number.
Here is the Actual code Im using. Its original skeleton is the code from the book.
My code works so far but why? lolz. you guys are great!
Im havin fun which is the important part!
Anyway.
The ADC0831 code is the heart of my current hack. I have modified it and added buzzers lights relays warnings and an LCD. It pretty cool. Of course I want to apply my new found Voltage monitor to a 12vdc system. I knew Id have to tackle the conversion issue since I will be using 5Vref. So off I went with my 8th grade math skillz, parallax basic stamp forum and google.
The stock code can be found on pages 156 -157 in Stamp works. Please note the $139c value for Cnts2Mv. The comment says that 5000 / 255 = 19.6. Awesome. I don't know Hex from a hole in the wall so I figured all of this was true. Using this information I came up with $1388 for the hex value. Curious, I plugged it in and now my display reads 4980. Hmmmm. Off to study Hex for a few hours......... I stumbled upon some awesome code while perusing the forums from Tracy Allen and hacked it up to help me solve the problem. Here it is...
'{$STAMP BS2sx} '{$PBASIC 2.5} ' ----------[ revision history ]------------------------------------------------ ' Tracy Allen, [URL="http://www.emesystems.com"]www.emesystems.com[/URL] when? ' Randy Cookson Hacked it up on July 2, 2014 ' This awsome Tracy Allen code was hacked up and reconfigured to find the HEX ' value for the conversion of the 255 bit result from the ADC0831 reading 5Vref to show the 12vdc scale on the debug ' and LCD. I got close. I have no Idea why the 0831 code used 5020 or #139c to ' get the terminal to show 5000 which is actully = $1388 Where did the 20 Hex points come from? idx VAR Byte precision VAR Word Hexcnt VAR Word hexnum VAR Word MultV VAR Word bitV VAR Word targetV VAR Word targetHEX VAR Word result VAR Word com VAR Byte main: DEBUG CLS DEBUG "First enter number of decimal places desired: " DEBUGIN DEC precision DEBUG CR DEBUG CLS, "Enter highest bit division # ie. 8 bit would be 255 " DEBUGIN SNUM bitV ' retrieve number in any format DEBUG CLS, CRSRXY, 6,0, "Decimal bit value:... ", DEC bitv DEBUG CRSRXY, 0,2, "Enter desired display result. ie. 5000 " DEBUGIN SDEC targetV DEBUG CRSRXY,0,2,CLREOL DEBUG CRSRXY, 6,1, "Target Value entered is:.. ", DEC targetV ,CR MultV = targetV + 20 '<<<<<<<< CRITICAL WTF CODE HERE DEBUG CRSRXY, 6,2,DEC targetV," / ",DEC bitV," = ", DEC targetV/bitV,"." ' main digit kicker outer... FOR idx=1 TO precision-1 targetV=targetV//bitV*10 DEBUG DEC1 targetV/bitV NEXT DEBUG DEC1 (targetV//bitV*10+5/bitV),CR,CR ' round off final digit DEBUG CRSRXY, 0,8, HEX MultV
After hours with various beans and pieces of paper I discovered that If I add 20 to my targetV variable (now MultV) I get the desired output for finding the HEX value.
I have figured out what the Hex conversion for 12v is. I think its $2f10. Why is the question. Why do I have to add 20 to the HEX value to get my targeted number.
Here is the Actual code Im using. Its original skeleton is the code from the book.
' {$STAMP BS2sx} ' {$PBASIC 2.5} ' ' ========================================================================= ' -----[ Program Description ]--------------------------------------------- ' 'Battery monitory with LCD display. '--------[0831 pinout to stamp--------------------------------------------- ' 0831 pin 1 CS MCU 0 ' 0831 pin 2 Vin+ wiper 10k pot with 220 Resistor (pot = VDD / VSS) ' 0831 pin 3 Vin- VSS (GND) ' 0831 pin 4 GND VSS (GND) ' 0831 PIN 5 Vref VDD +5VDC (this will be from Vref chip) ' 0831 pin 6 DO MCU 2 ' 0831 PIN 7 CLK MCU 1 ' 0831 PIN 8 VCC VCC +5VDC ' -----[ I/O Definitions ]------------------------------------------------- CS PIN 0 ' chip select (ADC0831.1) Clock PIN 1 ' clock (ADC0831.7) DataIn PIN 2 ' data (ADC0831.6) ' -----[ Constants ]------------------------------------------------------- BAUD CON $406e 'Set Baud rate to 19200 inverted BS2 = $4020 BS2sx = $406e CLR CON 012 'LCD Clear Screen instruction LINE1 CON 001 'Cursor Home Position TX CON 9 Spkr PIN 4 freq CON 1500 freqtime CON 200 BatFull CON 12000 BatRecover CON 11900 BatLow CON 11800 BatCrit CON 11700 BatDead CON 11500 Bat_Good_led CON 10 Alarm1 CON 12 Alarm2 CON 11 SysPower CON 5 Sdelay CON 10 Cnts2Mv CON $2f10 ' x 19.6 ((Actually this hex is 5020 dec) ' (TO millivolts) $139c is the original value. ' -----[ Variables ]------------------------------------------------------- LCDVolts VAR Word result VAR Byte ' result of conversion mVolts VAR Word ' millivolts ' -----[LCD initialize]---------------------------------------------------- Initialize: PAUSE 2000 Recover: LOW Alarm1 LOW Alarm2 FREQOUT Spkr, freqtime, freq HIGH tx PAUSE 200 SEROUT TX,BAUD,[003] 'RESTORE DISPLAY SEROUT TX,BAUD,[015,040] 'Set Contrast SEROUT TX,BAUD,[020] 'Turn Scroll Off SEROUT TX,BAUD,[024] 'Turn Wrap Off SEROUT TX,BAUD,[004] 'Turn Cursor Off SEROUT TX,BAUD,[CLR] 'Clear Screen SEROUT TX,BAUD,[LINE1] 'Goto Home Position SEROUT TX,BAUD,[" Power Monitor"] 'Display Text SEROUT TX,BAUD,[017,000,001] 'Position Cursor at Col 1 of Line 2 on LCD SEROUT TX,BAUD,[" Running"] 'Display Text PAUSE 1000 'Pause SEROUT TX,BAUD,[CLR] 'Clear Screen ' -----[ Initialization ]-------------------------------------------------- Reset: DEBUG CLS, ' create report screen "ADC.... ", CR, "volts... " ' -----[ Program Code ]---------------------------------------------------- Main: HIGH Bat_Good_led LOW Alarm1 LOW Alarm2 HIGH SysPower ' connecy or disconnect all loads DO GOSUB Read_0831 ' read the ADC mVolts = result */ Cnts2Mv ' convert to millivolts DEBUG HOME, ' report CRSRXY, 9, 0, DEC result, CLREOL, CRSRXY, 9, 1, DEC mVolts SEROUT TX,BAUD,[020] 'Turn Scroll Off SEROUT TX,BAUD,[024] 'Turn Wrap Off SEROUT TX,BAUD,[004] 'Turn Cursor Off SEROUT TX,BAUD,[LINE1] 'Goto Home Position SEROUT TX,BAUD,["Millivolts ",DEC5 mVolts] SEROUT TX,BAUD,[017,000,001] SEROUT TX,BAUD,["Sys. Oporational"] IF mVolts < BatLow THEN GOTO Low_Battery: ELSEIF mVolts < BatCrit THEN GOTO Bat_Critical: ELSEIF mVolts < BatDead THEN GOTO Emergency_stop: ENDIF LOOP '-------------------------- [Sub routine]------------------------------------------- Read_0831: LOW CS ' enable ADC SHIFTIN DataIn, Clock, MSBPOST, [result\9] ' read ADC HIGH CS ' disable ADC RETURN '-------------------------- [Sub routine]-------------------------------------------- Low_Battery: LOW Bat_Good_led DO PWM Alarm1,255,100 GOSUB Read_0831 ' read the ADC mVolts = result */ Cnts2Mv ' convert to millivolts DEBUG HOME, ' report CRSRXY, 9, 0, DEC result, CLREOL, CRSRXY, 9, 1, DEC mVolts DIG 3, ".", DEC3 mVolts SEROUT TX,BAUD,[020] 'Turn Scroll Off SEROUT TX,BAUD,[024] 'Turn Wrap Off SEROUT TX,BAUD,[004] 'Turn Cursor Off SEROUT TX,BAUD,[LINE1] 'Goto Home Position SEROUT TX,BAUD, ["Millivolts ", DEC5 mVolts] SEROUT TX,BAUD,[017,000,001] SEROUT TX,BAUD, [" Low Battery "] IF mVolts < BatCrit THEN GOTO Bat_Critical: ELSEIF mVolts < BatDead THEN GOTO Emergency_stop: ELSEIF mVolts > BatRecover THEN GOTO Main: ENDIF LOOP '-------------------------- [Sub routine]------------------------------------------- Bat_Critical: DO PWM Alarm2,200,200 PWM Alarm1,255,200 GOSUB Read_0831 ' read the ADC mVolts = result */ Cnts2Mv ' convert to millivolts DEBUG HOME, ' report CRSRXY, 9, 0, DEC result, CLREOL, CRSRXY, 9, 1, DEC mVolts DIG 3, ".", DEC3 mVolts SEROUT TX,BAUD,[020] 'Turn Scroll Off SEROUT TX,BAUD,[024] 'Turn Wrap Off SEROUT TX,BAUD,[004] 'Turn Cursor Off SEROUT TX,BAUD,[LINE1] 'Goto Home Position SEROUT TX, BAUD, ["Millivolts ", DEC5 mVolts] SEROUT TX,BAUD,[017,000,001] SEROUT TX, BAUD, ["Battery Critical"] IF mVolts > BatLow THEN GOTO Low_Battery: ELSEIF mVolts < BatDead THEN GOTO Emergency_stop: ENDIF LOOP Emergency_stop: SEROUT TX,BAUD,[003] 'Hide display SEROUT TX,BAUD,[015,040] SEROUT TX,BAUD,[020] 'Turn Scroll Off SEROUT TX,BAUD,[024] 'Turn Wrap Off SEROUT TX,BAUD,[004] 'Turn Cursor Off SEROUT TX,BAUD,[CLR] 'Clear Screen SEROUT TX,BAUD,[LINE1] 'Goto Home Position SEROUT TX,BAUD,[" Battery at "] 'Display Text SEROUT TX,BAUD,[017,000,001] 'Position Cursor at Col 1 of Line 2 on LCD SEROUT TX,BAUD,[" unsafe level"] 'Display Text PAUSE 1000 'Pause SEROUT TX,BAUD,[CLR] 'Clear Screen SEROUT TX,BAUD,[" Battery at "] 'Display Text SEROUT TX,BAUD,[017,000,001] 'Position Cursor at Col 1 of Line 2 on LCD SEROUT TX,BAUD,[" unsafe level"] 'Display Text PAUSE 1000 SEROUT TX,BAUD,[020] 'Turn Scroll Off SEROUT TX,BAUD,[024] 'Turn Wrap Off SEROUT TX,BAUD,[004] 'Turn Cursor Off SEROUT TX,BAUD,[LINE1] 'Goto Home Position SEROUT TX, BAUD, [" Shutting down"] PAUSE 1000 FREQOUT Spkr,1500,1500 LOW SysPower DO HIGH Alarm2 GOSUB Read_0831 ' read the ADC mVolts = result */ Cnts2Mv ' convert to millivolts DEBUG HOME, ' report CRSRXY, 9, 0, DEC result, CLREOL, CRSRXY, 9, 1, DEC mVolts DIG 3, ".", DEC3 mVolts SEROUT TX,BAUD,[020] 'Turn Scroll Off SEROUT TX,BAUD,[024] 'Turn Wrap Off SEROUT TX,BAUD,[004] 'Turn Cursor Off SEROUT TX,BAUD,[LINE1] 'Goto Home Position SEROUT TX, BAUD, ["Millivolts ", DEC5 mVolts] SEROUT TX,BAUD,[017,000,001] SEROUT TX,BAUD,[" Standby mode..."] LOW Alarm2 PAUSE 3000 'charge stand by MODIFY FOR LONGER DELAY BASED ON CSD. SEROUT TX,BAUD,[003] IF mVolts > BatRecover THEN PAUSE 2500 SEROUT TX,BAUD,[017,000,001] SEROUT TX,BAUD,[" 12 Vdc detected!"] PAUSE 2500 LOW Alarm2 GOTO Recover: ENDIF LOOP
My code works so far but why? lolz. you guys are great!
Comments
Page 158 of StampWorks it says:
Dividing five (volts) by 255, we find that each bit in the result is equal to 19.6 millivolts.
For display purposes, the result is converted to millivolts by multiplying by 19.6 (result */ $139C).
On page 160, its also says:
With a Vref of 2.55 volts, the voltage per bit is 0.01 volts, nearly twice as when 5.00 volts was used, for Vref, and the conversion to millivolts is simplified.
...
Before running the program modify the Cnts2Mv constant to reflect the Vref change.
With each bit equal to 0.01 volts (1/100) we can multiply by 10 to covert to millivolts (1/1000).
Cnts2Mv CON $0A00 ' x 10 (to millivolts)
Refer to Page 85 of What's a Microcontroller? V3.0 for an explanation of the */ operator.
Step 2 says take the fractional value that you want to use and multiply it by 256.
Here's the math:
Reference Voltage / # of bits for the ADC = Volts per bit
The ADC0831 is 8-bit so it outputs a value from 0 to 255 (2^8 = 256).
Vref = 5V
5V / 255 = 0.019607843 which rounds up to 0.01961 volts per bit or 19.61 mV per bit.
19.61 x 256 = 5020.16 which rounds up to 5020 which is $139C, for mV per bit.
Vref = 2.55V
2.55V / 255 = 0.01 V / Bit = 10 mV per bit
10 x 256 = 2560 = $0A00, for mV per bit
Hexadecimal is Base-16 so the digits range from 0 to F.
0-9, A = 10, B = 11, C = 12, D = 13, E = 14, F = 15
$139C = 1(16^3) + 3(16^2) + 9(16^1) + C=12(16^0) = 1(4096) + 3(256) + 9(16) + 12(1) = 4096 + 768 + 144 +12 = 5020
Remember from algebra, that anything raised to the 0 power is 1 (by definition).
$0A000 = 0(16^3) + A=10(16^2) + 0(16^1) + 0(16^0=1) = 0 +10(256) + 0 + 0 = 2560
The Windows calculator has a built in converter so click View - Programmer. Click View - Standard to return to the regular calculator mode.
Some scientific calculators also have Hex - Dec and vice-versa conversion.
I noticed that your program using GOTOs within a DO-LOOP which is very bad practice. Instead you should use what's called a State Machine.
The State changes with conditions and code is executed or skipped depending on the current State.
Anything connected to an I/O pin should be a PIN and not a CON variable.
You have a lot of LCD code so put as much of it as you can in a subroutine or a set of subroutines.
Do you have a schematic of your circuit?
I don't see any reason why you need to use hexadecimal in your code at all.
Your code is really hard to read. I think the BS2 editor will automatically indent the code for you. Please do this in the future. It will make reading your code much easier. Thanks for using code tags.
As Genetix points out your code has structural issues but then most us on the forum had structural issues with our code at one time. I hope you don't get discouraged when one of us says "you're doing it wrong". I personally learn the most from "you're doing it wrong type posts" (when directed at myself).
What are SysPower, Alarm1, and Alarm2 and better explain what should happen when each state changes.
Why do you first HIGH and LOW the Alarms and then later use PWM?
I see you have a short and long speaker tone that I adjusted since the BS2SX is not the same speed as the BS2.