Excuse the stupid title, but apparently I am the victim of the notorious "too long title" bug. I wanted the title to be, "PBP ADC to voltage conversion help." I want to read a pot, and convert its ADC10 digital value to voltage. Each step represents .004V. My conversion routine works up through a digital value of 999, but is wrong at 1000 and above. For example a digital value of 903 converts to a voltage of 3.612 (correct), but a digital value of 1007 converts to 4.24V when it should be 4.024V. The PicBasic Pro code follows; please tell me how to correct it. Thanks. Code ( (Unknown Language)): start: ADCIN 0, left_pot 'Reads analog voltage on AN0, converts it to 10-bit 'digital value, and stores it as left_pot. y = (left_pot*4) whole = y/1000 decimal = y//1000 LCDOUT $FE,1,"Left Pot = ", DEC left_pot 'Clears LCD screen, displays '"Left Pot = " and the decimal value of left_pot. lcdout $FE,$C0,"Voltage = ", #whole, ".", #decimal
Decimal is only two digits - the leading zero is lopped off. Either lcdout a zero before printing the remainder if decimal < 100, or divide for each digit value and print it out for each decimal place...
Sure.... Where result = raw_ADC *4 Thousands = (result MOD 10000)/1000 Hundreds = (result MOD 1000)/100 Tens = (result MOD 100)/10 Units = (result MOD 10) Or there are better algorithms out there...
Okay, it is working as I had hoped. I need to study the MOD operator in an effort to understand exactly what's happening. On a side note, I have my external reference quite steady at 4.096V as measured with my Fluke 115. When I use that same meter to measure the voltage out of the pot, it is consistently different by .006V from the calculated voltage. Do you have any idea why that is? Thanks again for the code help.
Sorry, I shouldn't assume - it is commonly called a mod operator(like the mod counter) and, like the mod counter, is actually the modulus operation (or taking the modulo) - essentially the "//" division you were doing in your code. I'm afraid I'm not familiar with your setup, but assuming you are just using the potentiometer as a voltage divider, I would suspect the difference to be from the quantization error of each of the measuring devices.
I want to be sure I understand how the modulus operation works in my code. Code ( (Unknown Language)): ADCIN 0, left_pot 'Reads analog voltage on AN0, converts it to 10-bit digital value, and stores it as left_pot. lpot = (left_pot*4) lthousands = (lpot//10000)/1000 lhundreds = (lpot//1000)/100 ltens = (lpot//100)/10 lunits = (lpot//10) If lpot = 3456, then lthousands is calculated as follows. 3456 is divided by 10000 quotient is 0 remainder is 3456 remainder is divided by 1000 quotient is 3 (because .456 is truncated) lthousands is therefore 3 Correct? Thanks.
Yup, you just need to be careful that the number is an integer type, or is at least truncated properly. You don't need to do the modulus on the thousands place since it will never be in the ten thousands digit - you can just divide by 1000 (I put it in for consistency). Of course, leaving it in won't hurt anything but cycle time, but the modulus on the highest digit position doesn't give you any new information.
Thanks for the help. It's really nice to know how code works (even if I didn't write it myself.) Here's a photo of my test setup. The little assembly toward the top left is my TL431A 4.096V reference circuit.
Wow, you really enjoy making modular setups! I had assumed you wrote it, had I not, I would have been more thorough in my initial explanation, sorry. The double dabble approach (the alternative I linked to before) is faster, but not as clear when looking at the code. It doesn't seem like you are too concerned with speed now, but a good thing to know for future endeavors...
I did write the original that I posted, if one can really say he wrote any code. It's more accurate to say that I cobbled it together from bits and pieces. That's pretty much the way all my code comes together...a bit at a time...with help from people like you.
From my stint as a software engineer, I'd say that's how all code is written! The key is understanding what the Frankencode means...
Doesn't the compiler already have a function to convert a unsigned 16bit variable into an ascii text number? In C you just use itoa() or WordToString() etc.
I don't know, but I just posted the question over on the picbasic pro forum. I'll post the answer if/when it comes. Thanks for wording the question for me.
Here is what appears to be the shortest way to what I needed. Thanks to all for your input. Code ( (Unknown Language)): ' Aliases and Modifiers: ' Program Code: PAUSE 1000 'Pauses 1 second to allow LCD to setup. start: ADCIN 0, left_pot 'Reads analog voltage on AN0, converts it to 10-bit digital 'value, and stores it as left_pot. lpot = (left_pot*4) 'Multiplies left_pot times 4 to get 1000x voltage. ADCIN 1, right_pot 'Reads analog voltage on AN1, converts it to 10-bit digital 'value and stores it as right_pot. rpot = (right_pot*4) 'Multiplies right_pot times 4 to get 1000x voltage. LCDOUT $FE,1,"Left Pot = ", DEC left_pot 'Clears LCD screen, displays '"Left Pot = " and the decimal ADC of left_pot. LCDOUT $FE,$C0, "Voltage = ", DEC lpot/1000, ".", DEC3 lpot//1000 'Displays result to 3 decimal places. LCDOUT $FE,$94,"Right Pot = ", DEC right_pot 'Sets LCD to beginning of 'second line and displays "Right Pot = " and the decimal ADC of 'right_pot. LCDOUT $FE,$D4, "Voltage = ", DEC rpot/1000, ".", DEC3 rpot//1000 'Displays result to 3 decimal places.
Nicely done! You've used the ability of the LCDOUT function to display multiple strings in sequence. Neat and clean. If I was to find something to criticise, what are the "magic hex numbers" after LCDOUT? LCDOUT $FE,$D4 I assume the second one is the line and column indexing, is the first one a move command? ie; FE=move D4=whereto? It would be a nice fix to replace those with text constants if possible. That makes the code easier to read and more importantly easier to write.
The $FE indicates that what follows is a control code; the next $XX is the line indicator for the display. Thanks for the compliment, but I got a lot of help. The upside is that I know how to do it now!