Displaying 0 - 359 degrees on a LCD display for rotary encoder - anemometer

Orbicim

New Member
Hi everyone,

Hope someone can help here. I have built an anemometer and I'm using the code shown below, a butchered version of a few peoples code that has been here before.

The issue is that I am wanting the encoder to show 0 - 359 degrees rather than the Data Variable max which shows up to 255. Is there any way to do this?
I have tried the code with word variables however it didn't work on the LCD display, the encoder had no effect.

I'm at a bit of a loss here, I have tried searching through the forum and found this: http://www.picaxeforum.co.uk/showthread.php?23182-how-to-count-and-display-above-255-help-needed however I don't really understand what is happening. I have tried to do what it says but (a) it didn't work and (b) I would like to know what is happening even if it did work.

Any help is much appreciated


Code:
initiate: serout C.6,N2400,(254,1) 				;clear display
          pause 500 						;allows time for LCD to reset
          
serout C.6,N2400,(254,128)          			;first row of the first line
         serout C.6,N2400,("Mikes Anemometer") 		;print message
         pause 5000     					;pause 5 seconds
         serout C.6,N2400,(254,1) 				;clear display
         pause 500   						;allows LCD to reset

symbol getBits   = b0 						'b0 = bit7 : bit6 : bit5 : bit4 : bit3 : bit2 : bit1 : bit0
symbol dir       = b1						
symbol counter   = b3						

setint %00000001,%00000001 					'interrupt on pinC.0 high only

 main:
 
	
 do
 bintoascii b4, b5,b6,b7					;changes b4 output to 3 ascii characters
 bintoascii b8, b9,b10,b11					;changes b8 output to 3 ascii characters
 serout C.6,N2400,(254,128,"Angle=",b5,b6,b7)		;Top line is Angle=XXX
 serout C.6,N2400,(254,192,"Windspeed=",b9,b10,b11)	;Bottom line is Windspeed=XXX
 count C.2, 1000, b8				 		;Counts B8 pulses to give RPS
 loop									;loop back to main

 interrupt:
 bit1 = pinC.1: bit0 = pinC.0 				'save rotary encoder pins status
 getBits = getBits & %000000011				'isolate rotary encoder pins
 if getBits <> 0 then 						'if both pins are low, the direction is undetermined: discard
 dir = bit1 * 2 							'direction: if bit1=low then dir=0; if bit1=high then dir=2
 counter = counter - 1 + dir 					'change counter variable accordingly
 b4 = b3*15								;Because 15 degrees incriments, multiplied accordingly
 do while getBits <> 0 						'wait for the encoder to go to the next "detent" position
 getBits = pinsC & %000000011					;isolate rotary ecoder pins
 loop									;loops program
 endif								;terminate multiple lines
 setint %00000001,%00000001					'restore interrupt on pinC.0 high
 return
View attachment Finale.bas
 
Last edited:

eggdweather

Senior Member
Replace b4 with a word variable, say w2 or

symbol angle = w2 (which is the same as b4 and b5 and move all variables after b4 up one, so what was b5 becomes b6)

Remove the code lines to convert BINTOBCD they are not required and can be replaced with # in the print statements), see manual exert:

SERTXD ({#}data,{#}data...)
The # symbol allows ASCII output. Therefore #b1, when b1 contains the data 126, will output the ascii characters "1" "2" "6" rather than the raw data 126. The # symbol can also be used with word, bit and input pin variables.

Your code then becomes:
angle = angle * 359/16' to scale 0 to 15 to 0 to 359

serout C.6,N2400,(254,128,"Angle=",#angle)

And in your interrupt routine change the line:
b4 = b3*15
to
b4 = b3

You could also add:
symbol wind_speed = w3
And change:
serout C.6,N2400,(254,192,"Windspeed=",b9,b10,b11)
to
serout C.6,N2400,(254,192,"Windspeed=",#wind_speed)

Code:
symbol getBits	= b0 						'b0 = bit7 : bit6 : bit5 : bit4 : bit3 : bit2 : bit1 : bit0
symbol dir		= b1						
symbol counter	= b3
symbol angle	= w2
symbol w_speed= w3

initiate: serout C.6,N2400,(254,1)	;clear display
pause 500 						;allows time for LCD to reset
          
serout C.6,N2400,(254,128)				;first row of the first line
         serout C.6,N2400,("Mikes Anemometer")	;print message
         pause 5000						;pause 5 seconds
         serout C.6,N2400,(254,1) 				;clear display
         pause 500   						;allows LCD to reset

setint %00000001,%00000001				;interrupt on pinC.0 high only

main:
do
   serout C.6,N2400,(254,128,"Angle=",#angle)			;Top line is Angle=XXX
   serout C.6,N2400,(254,192,"Windspeed=",#w_speed)	;Bottom line is Windspeed=XXX
   count C.2, 1000, w_speed				 		;Counts B8 pulses to give RPS
loop					  						;loop back to main

interrupt:
bit1 = pinC.1: bit0 = pinC.0			'save rotary encoder pins status
getBits = getBits & %000000011			'isolate rotary encoder pins
if getBits <> 0 then 					'if both pins are low, the direction is undetermined: discard
   dir = bit1 * 2						'direction: if bit1=low then dir=0; if bit1=high then dir=2
   counter = counter - 1 + dir			'change counter variable accordingly
   angle = b3						'Because 16 increments or 22.5degs/step
   do while getBits <> 0				'wait for the encoder to go to the next "detent" position
     getBits = pinsC & %000000011		'isolate rotary decoder pins
   loop							'loops program
endif								'terminate multiple lines
setint %00000001,%00000001			'restore interrupt on pinC.0 high
return
 
Last edited:

AllyCat

Senior Member
Hi,

Basically, you just need to multiply your present value by 360 and divide by the current "fullscale" (i.e. 256). You must multiply first (integer division will give a zero value) but a value near to 255* 360 will overflow even a word.

So you need to divide by at least 2 somewhere first (perhaps your raw data). The easiest is probably to multiply by only 180 (or 90 or 45) and then divide by 128 (or 64 or 32) to compensate. Then display the data Word as normal (e.g. using #Wn , as in #2 above).

Cheers, Alan.
 

Orbicim

New Member
Hmmm I tried your ideas/code but didn't work, made the LCD display go berzerk with the encoder. I'll keep trying diff ideas. Cheers for the help though
 

AllyCat

Senior Member
Hi,

We need more information about your hardware, but I rather doubt if what you are atempting can be made to work in practice. You are trying to do too much in the interrupt routine and also, I believe that the Count command will "block" interrupts whilst it executes.

If the "encoder" is intended to measure wind direction, how can it determine "North"? Even without the complications of using interrupts with "blocking" commands, some pulses are bound to be lost (or their direction mis-interpreted) eventually.

It would probably be better not to use interrupts at all. But if you do, a very simple/fast interrupt routine should probably be used to count the wind pulses, with the wind direction as the "main" task.

Cheers, Alan.
 

hippy

Technical Support
Staff member
Trying to debug complete programs can be hard, as it is never clear where the problems may lie and there may be multiple issues.

It is probably best to write two separate programs to start with; one to read the anemometer data and display the results using the serial terminal rather than LCD, and another which gets the LCD working using known values without relying on the anemometer data. Once both are working you can merge them into a single program.
 

eggdweather

Senior Member
There are two wind direction sensor type that I'm aware of:
1. A set of reed switches that switch in various values to resistor into a voltage divider chain and the resultant voltage is measured by an ADC to give direction - easy, but he's not using that type.
2. A dual switched output type, where one output pulses each time the anemometer rotates and it always pulses at effectively what is time-zero and the direction line pulses some time after the reference pulse depending on direction angle, so there are two square waves coming out, one the reference and the other direction, so to determine direction needs the difference in time between the two lines to be measured (say +positive edges) and the difference between that and the time taken to rotate one rev (the last rev) gives the direction. The benefit is this arrangement allows wind speed to be determined from the same outputs by measuring PPS.
3. It's a home made sensor with 16-reed switches, but we need more detail to understand its operation.

Examination of the code shows it may be one of the latter types, but the reference point is not being determined only the count of direction angle changes, so it can't determined direction.

I agree with Hippy to do this in small logical steps and then work at combining the two codes.
 

premelec

Senior Member
@Orbicim - wind direction output is always [unless you are indoors measuring fans] very noisey... often the main problem is integrating the trash data that comes out of the weathervane as much as detecting position - good luck with it! If you are building a unit you might consider absolute position encoder wheel. [There was post of a program that generates these patterns a few years ago on this forum].
 

eggdweather

Senior Member
The use of a 'Gray' code as used in position encoders would help solve the problem of position, where only one bit changes state from one position to the next.
Dec Gray Binary
0 000 000
1 001 001
2 011 010
3 010 011
4 110 100
5 111 101
6 101 110
7 100 111
 

inglewoodpete

Senior Member
There are two wind direction sensor type that I'm aware of:
1. A set of reed switches....
2. A dual switched output type, where one output pulses each time the anemometer rotates and it always pulses....
The Davis Wind Vane/Anemometer combo, which I've used in a couple of projects, uses a 360 degree potentiometer (uses 5 volts end-to-end). I used a rail-to-rail op-amp to buffer the long lead-in. It included an R-C filter to remove noise.
 
Last edited:

AllyCat

Senior Member
Hi,

Yes there are numerous methods for determining wind direction, but it's interesting that the (arguably) "Market Leader" of serious amateur Weather Stations uses nothing more than a humble potentiometer. But it is quite expensive so presumably designed/specified for the job.

For a simple project it's hard to beat the "Fine Offset" (manufacturer) reed switch + resistors analogue method, particularly for battery operation. Personally, I find the "ultrasonic time of flight" method of most interest, and Derek Weston's "tagged anemometer" the most ingenious (discussed on the forum here).

A forum search may reveal quite a few relevant threads.

Cheers, Alan.
 
Top