Continue to Site

Welcome to our site!

Electro Tech is an online community (with over 170,000 members) who enjoy talking about and building electronic circuits, projects and gadgets. To participate you need to register. Registration is free. Click here to register now.

  • Welcome to our site! Electro Tech is an online community (with over 170,000 members) who enjoy talking about and building electronic circuits, projects and gadgets. To participate you need to register. Registration is free. Click here to register now.

:: ADC - Missing Bits :: HELPP

Status
Not open for further replies.

suby786

New Member
Hey All,

In my project, i need to acquire 4 voltages and they are connected to AN0-3, they convert fine, and I am requesting the conversion by sending the PIC a command from VISUAL BASIC - OVER A WIRELESS LINK which works. So i command the pic to take the reading... when im ready i then command the pic to return the two bytes of data back to the application for processing. This all works EXCEPT the conversion bits is INCORRECT.

I have RIGHT justified the ADC, so the LOW byte should contain 8 bits, and the HIGH byte should contain the last 2 bits.

The problem lies with the LOW BYTE, my value ONLY traverses from 0-127, not 256 as if it was TRUE 8 BIT. The HIGH byte is 0. Look below, it may come clearer.


Analog V / HIGH BYTE / LOW BYTE
0-0.6V / 0 / 0-127
0.6-1.2V / 0 / 63 (For some odd reason it is always 63)
1.2-1.8V / 1 / 0-127

etc etc

5V / 3 / xxxxx cant remember


So the HIGH byte traverses 0/1/2/3 as you'd expect from a 2 bit number, but i am missing the MSB of the LOW BYTE. What is happening? I dont think the VISUAL BASIC is dropping this bit off, but could it be the ADC?

Im missing a chunk of my voltage range


HELPPPPP


Code is BELOW:
Code:
ACQ_CH1
	CLRF	CH1_STAT
	;Set ADCON0 to turn on ch1 AND turn on GO/DONE
	MOVLW   b'10000101'
	MOVWF	ADCON0
	BSF		ADCON0, GO_DONE		;initiate conversion - Make Sure
	BTFSC   ADCON0, GO_DONE
    GOTO    $-1			;wait for ADC to finish

	BSF		STATUS,5	;;CHANGING STATUS TO BANK 1
	MOVF	ADRESL, W
	BCF		STATUS,5	;;CHANGING STATUS TO BANK 0
	MOVWF	CH1_STAT
	MOVF	ADRESH, W
	MOVWF	CH1_STAT_H
	
	;RESET BYTES TO 5 AND DEFAULT EVERYTHING
	MOVLW	h'05'
	MOVWF	BYTE
	MOVLW	h'01'		;Loads default value for MAGIC to 01
	MOVWF	MAGIC		;Loads dfault value to MAGIC
	GOTO 	LAST_CHANNEL
	

ACQ_RESULT_CH1
	MOVFW	CH1_STAT
	MOVWF	TXREG
	BSF 	TXSTA, TXEN
	MOVFW	CH1_STAT
	MOVWF	TXREG
	BSF 	TXSTA, TXEN

	MOVLW	h'05'
	MOVWF	BYTE
	MOVLW	h'01'		;Loads default value for MAGIC to 01
	MOVWF	MAGIC		;Loads dfault value to MAGIC
	GOTO 	LAST_CHANNEL

ACQ_RESULT_CH1_2
	MOVFW	CH1_STAT_H
	MOVWF	TXREG
	BSF 	TXSTA, TXEN
	MOVFW	CH1_STAT_H
	MOVWF	TXREG
	BSF 	TXSTA, TXEN

	MOVLW	h'05'
	MOVWF	BYTE
	MOVLW	h'01'		;Loads default value for MAGIC to 01
	MOVWF	MAGIC		;Loads dfault value to MAGIC
	GOTO 	LAST_CHANNEL
 
Last edited:
Convert the value to ASCII (either as three HEX nibbles, or four decimal digits), and send it like that, rather than eight bit binary values - it cures LOT'S of strange RS232/PC problems.
 
How do i convert the 8 bit binary values to ASCII on the PIC (16F877A)?

Nibbles = 4 bits yes?

So 3 x 4 nibbles is 12 bits, so i imply the MSB of the 3rd nibble to 0 so i have 12bits in total?

and are you sayin when i receive these 3 hex numbers, i compile all of them to make a 12bit number and this is my conversion of 0-1024????
 
Nigel you are legendary...

Ive take your principle of RS232 not likeing 8 bits and what Ive done is a bit nifty i have to say, probably bit longer than what you;d do but it works.

I check bit 7 of the low byte, if it is SET, then i know my visual basic will MISS IT OUT.

So i rotate LEFT the HIGH BYTE, if bit 7 of LOW BYTE is set, i then set BIT 0 of the HIGH BYTE, basically im splitting the 10 bits of data from its original 8/2 split, to 7/3 split.

And hey presto it works a treat, in visual basic i use this high byte value to add its units onto the low byte value, and i get a reading from 0-1024, well just under 1024.

Thanks for your help, code is below if you find a better way of doing what i said, i didnt want to make 3 transmissions to send 10bits, so the 7/3 split works better for me.

Code:
	RLF		CH1_STAT_H, 1	;Rotate LEFT (* by 2) and keep in same place
	BCF		CH1_STAT_H, 0	;Clear the 1st bit, JUST to make sure its empty
	BTFSC	CH1_STAT, 7		;Check bit 7 of low_byte to see if its SET
	BSF		CH1_STAT_H, 0	;If set, then set the 1st bit of the high byte
	BCF		CH1_STAT,7		;Then cler bit 7 of the low byte so RS232 ignores it
 
Interesting 'bodge' - and it cures the problem, but doesn't really locate the source of the problem?.

BTW, you could take it further, and send as two 5 bit sections.
 
i could take two 5 bit sections, but then i'd need to do alot more work in VB to combine the two section into one number 0-1024.

I know you say its a 'bodge' but the concept, how could you improve how I have done the 7/3 split????

That would be a great help if you can see a better way.
 
suby786 said:
i could take two 5 bit sections, but then i'd need to do alot more work in VB to combine the two section into one number 0-1024.

It would make no real difference either way, it's simple in both cases.

I know you say its a 'bodge' but the concept, how could you improve how I have done the 7/3 split????

I would have done it as ASCII - it makes life just SO much easier :D

That would be a great help if you can see a better way.

Like I said, I would have gone ASCII in the first place, but failing that I would try and find where the problem is - Windows by default is supposed to accept binary input to the serial port?, but I'd try checking that for a start - and make sure that low values (such as Null, CR or LF) don't give problems.

But as it works, go with it like that - "if it ain't broke, don't fix it!".
 
As Nigel says, send it as ASCII. I find the easiest way is to send it as hexadecimal followed by a Cr.

I use this code,
Code:
WriteHex	movwf	Temp;			save the value for later
		swapf	Temp,W;			move the high nibble into W
		call	WriteNibble;		write it
		movfw	Temp;			get the low nibble
WriteNibble	andlw	0fh;			fall through to write low nibble
		addlw	256-10 ; 		if a-f then carry set
		btfsc	STATUS,C;		was it A-F?
		addlw	7;			yes, adjust for A-F
		addlw	"0"+10;			convert to ASCII
SendByte	btfss	PIR1,TXIF;		wait for previous byte
		goto	SendByte;		to be sent
		movwf	TXREG;			send new byte.
		return

I would send a 16 bit value by doing,
Code:
		movfw	ValHi
		call	WriteHex
		movwf	ValLo
		call	WriteHex
		movlw	.13
		call	SendByte

On the PC end I would do the following in MSComm1_OnComm(),
Code:
    Received = Received & MSComm1.Input
    If InStr(Received, Chr(13)) <> 0 Then
	ReceivedValue = Val("&h" & Received)
	Received = Right(Received,Len(Received)-Instr(Received,Chr(13)))
    End If

The above code is for VB 5 or 6 - you can convert to .net. For the picky out there, change the Chr(13) to VbCr.

One nice thing about sending it as ASCII is that you can look at the received data in Hyperterminal to check it is OK. For it to work correctly with HT then you need to send a linefeed (chr(10)) after the Cr. You would of course change the VB to look for Chr(10) instead of 13.

HTH

Mike.
 
Last edited:
Status
Not open for further replies.

New Articles From Microcontroller Tips

Back
Top