PWM motor control via DS18b20 - assistance required

dotc0m

New Member
Good evening guys, I'm relatively new to picaxe programming and i'm working on a little task at the minute: using a temperature sensor (ds18b20) and microcontroller to vary the speed of a 5v motor. The motor is connected via a N-channel mosfet transistor with a diode to block some of the back emf.

I have each part of the circuit working if I use them separately; the sensor reads, the motor runs at varying speeds and the screen shows the display I want (except the temperature variable does not.)
When i put all the components into one program and wire the circuit up - i get a motor running at what i'm guessing is 100% and no temperature readout on the OLED screen.

I know my coding is possibly not the best way to do a pulse width modulation project, but like i said this is my first attempt. I've included my latest coding attempt below; if anyone has any help as to where i may be going wrong i'd be very grateful.

EDIT: i am using an 18m2 project board, the output pin for the OLED screen is soldered directly to the pin of the IC chip and not through the darlington driver. I have the transistor connected to b.3 and the sensor connected to c.1

Regards


Code:
;	Constants:
symbol temperature = b1		;Rename b0 variable to temperature
symbol pwmfan = b.6		;Rename pin b.6 to Pwmfan
symbol tempsens = c.1		;Rename pin c.0 to tempsens


;	Temperature Settings
;	--------------------------------------------
;	Temperature		Fan Speed		PWM duty
;
;	<= 20			30%			119
;	21			41%			159
;	22			50%			199
;	23			58%			231
;	24			67%			267
;	25			75%			299
;	26			80%			319
;	28			90%			359
;	>=30			100%			399
;
;	--------------------------------------------


main:
READTEMP tempsens, temperature		; read the temperature of DS18B20 on pin c.0, load variable into b1
debug b1
serout b.2, n2400, ( 254, 1 )					; Clear OLED display
pause 50								; pause to clear
serout b.2, n2400, ( 254, $80 )				; First line of display 
serout b.2, n2400, ( "Temperature" )			; Display "Temperature" 
serout b.2, n2400, ( 254, $C0 )				; Second line of display 
serout b.2, n2400, ( #temperature, "C" )			; Display the temperature 
wait 2						; wait 2 seconds							
	if temperature <=20 then lowspeed	; if variable in b1 is less than or equal to 20 degrees goto section
	if temperature =21 then speedforty	; if variable in b1 is equal to 21 degrees goto section
	if temperature =22 then speedfifty	; if variable in b1 is equal to 22 degrees goto section
	if temperature =23 then speedfive8	; if variable in b1 is equal to 23 degrees goto section
	if temperature =24 then speedsix7	; if variable in b1 is equal to 24 degrees goto section
	if temperature =25 then speedseven5	; if variable in b1 is equal to 25 degrees goto section
	if temperature =26 then speedeight0	; if variable in b1 is equal to 26 degrees goto section
	if temperature =28 then speednine0	; if variable in b1 is equal to 28 degrees goto section
	if temperature >=30 then fullspeed	; if variable in b1 is more than or equal to 30 degrees goto section
goto main						; return to main


lowspeed:
peek temperature, b1						; check temperature in variable b1
if temperature >20 then goto main				; if temperature is more than 20 degrees return to main
if temperature <=20 then pwmout B.3, 99, 119 endif	; if temperature is less or equal to 20 degrees, adjust pwm to 10000Hz at 30% @ 4MHz
pause 1000								; wait 1 second
goto lowspeed							; return

speedforty:
peek temperature, b1						; check temperature in variable b1
if temperature <>21 then goto main				; if temperature is more or less than 21 degrees, return to main
if temperature = 21 then pwmout B.3, 99, 159 endif	; if temperature is 21 degrees, adjust pwm to 10000Hz at 40% @ 4MHz
pause 1000								; Wait 1 second
goto speedforty							; return

speedfifty:
peek temperature, b1						; check temperature in variable b1
if temperature <>22 then goto main				; if temperature is more or less than 21 degrees, return to main
if temperature = 22 then pwmout B.3, 99, 199 endif 	; 10000Hz at 50% @ 4MHz
pause 1000								; Wait 1 second
goto speedfifty							; return

speedfive8:
peek temperature, b1						; check temperature in variable b1
if temperature <>23 then goto main				; if temperature is more or less than 23 return to main
if temperature = 23 then pwmout B.3, 99, 231 endif 	; if temperature is 23 degrees, adjust pwm to 10000Hz at 58% @ 4MHz
pause 1000								; Wait 1 second
goto speedfive8							; return

speedsix7:
peek temperature, b1						; check temperature in variable b1	
if temperature <>24 then goto main				; if temperature is more or less than 24 degrees return to main
if temperature = 24 then pwmout B.3, 99, 267 endif 	; if temperature is 24 degrees, adjust pwm to 10000Hz at 67% @ 4MHz
pause 1000								; Wait 1 second
goto speedsix7							; return

speedseven5:
peek temperature, b1						; check temperature in variable b1
if temperature <>25 then goto main				; if temperature is more or less than 25 degrees return to main
if temperature = 25 then pwmout B.3, 99, 299 endif 	; if temperature is 25 degrees, adjust pwm to 10000Hz at 75% @ 4MHz
pause 1000								; Wait 1 second
goto speedseven5							; return

speedeight0:
peek temperature, b1						; check temperature in variable b1
if temperature <>26 then goto main				; if temperature is more or less than 26 degrees return to main
if temperature = 26 then pwmout B.3, 99, 319 endif	; if temperature is 26 degrees, adjust pwm to 10000Hz at 80% @ 4MHz
pause 1000								; Wait 1 second
goto speedeight0							; return

speednine0:
peek temperature, b1						; check temperature in variable b1
if temperature <>28 then goto main				; if temperature is more or less than 28 degrees return to main
if temperature = 28 then pwmout B.3, 99, 359 endif	; if temperature is 28 degrees, adjust pwm to 10000Hz at 90% @ 4MHz
pause 1000								; Wait 1 second
goto speednine0							; return

fullspeed:
peek temperature, b1						; check temperature in variable b1
if temperature <30 then goto main				; if temperature is less than 30 degrees return to main
if temperature >= 30 then pwmout B.3, 99, 399 endif 	; if temperature is more than or equal to 30 degrees, adjust pwm to 10000Hz at 100% @ 4MHz
pause 1000								; Wait 1 second
goto fullspeed							; return

end
 
Last edited:

tmfkam

Senior Member
At first glance, you seem to be 'Peek'-ing the location referenced by the value of temperature, into the variable location b1. This result of this is likely to be unpredictable unless you've stored some values into that specific location (it doesn't look as though you have). As b1 appears to be the variable temperature, I'd expect you may be overwriting the value of temperature with a random number. I can't see why you are doing the 'Peek' operation, I'd firstly try commenting all the 'Peek' commands then trying again.

Once you are in one of your 'Speed' Sub-routines, the value of temperature isn't read again from the DS18B20 so they will never go back to the main procedure. You might need to consider either re-reading the temperature after your 'Pause 1000' command, or returning to the main procedure after the pause 1000 in order to update the LCD screen and re-check the current temperature.
 

PhilHornby

Senior Member
Some more thoughts

In addition to getting rid of the "peeks": you could simplify your code by having the "if" selection pull out the correct PWM value and pass it to a common section for processing - which gets rid of a lot of duplication.

In my code below, the multiple 'if's are replaced by the statement "offset = Temperature MIN 20 MAX 30 - 20", which first constrains the temperature value to be somewhere in the 20 -> 30 range, then 0->10. Once you've done that, you can use it as an index in a 'lookup' statement that plucks the correct PWM duty cycle value out of a list. (I defined symbols for the values, so you can easily change them at a single location).

Some other observations:
  1. You hadn't got entries for 27 & 29 degrees,
  2. It's probably more usual to issue a single pwmout instruction, and then vary it using pwmduty. I don't know if it makes much difference though.
  3. You could get rid of all the delays, and thus sample the temperature more frequently. As it stands, this would probably produce undesirable flickering on your LCD. If you make use of the 'multi-tasking' capabilities of the M2 series, you can have the LCD update running every (say) 10 seconds and the temperature/motor loop running continuously. (The temperature reading takes 750mS anyway).
  4. The finished project looks like it would run happily on an 08M2, rather than needing an 18M2. (Change of PWM pin needed though).



Code:
[COLOR=navy]#picaxe [/COLOR][COLOR=black]18m2[/COLOR]


[COLOR=green];     Constants:[/COLOR]
[COLOR=blue]symbol [/COLOR][COLOR=purple]temperature [/COLOR][COLOR=darkcyan]= [/COLOR][COLOR=purple]b1       [/COLOR][COLOR=green];Rename b0 variable to temperature[/COLOR]
[COLOR=blue]symbol pwmfan [/COLOR][COLOR=darkcyan]= [/COLOR][COLOR=blue]b.6           [/COLOR][COLOR=green];Rename pin b.6 to Pwmfan[/COLOR]
[COLOR=blue]symbol tempsens [/COLOR][COLOR=darkcyan]= [/COLOR][COLOR=blue]c.1         [/COLOR][COLOR=green];Rename pin c.0 to tempsens[/COLOR]
[COLOR=blue]symbol [/COLOR][COLOR=purple]offset [/COLOR][COLOR=darkcyan]= [/COLOR][COLOR=purple]b2            [/COLOR][COLOR=green];temporary. variable[/COLOR]
[COLOR=blue]symbol [/COLOR][COLOR=purple]PWMCycle [/COLOR][COLOR=darkcyan]= [/COLOR][COLOR=purple]W2          [/COLOR][COLOR=green];Setting for PWM cycle


;     Temperature Settings
;     --------------------------------------------
;     Temperature       Fan Speed         PWM duty
;
;     <= 20             30%               119
;     21                41%               159
;     22                50%               199
;     23                58%               231
;     24                67%               267
;     25                75%               299
;     26                80%               319
;     28                90%               359
;     >=30              100%              399
;
;     --------------------------------------------[/COLOR]


[COLOR=blue]symbol T20 [/COLOR][COLOR=darkcyan]= [/COLOR][COLOR=navy]119[/COLOR]
[COLOR=blue]symbol T21 [/COLOR][COLOR=darkcyan]= [/COLOR][COLOR=navy]159[/COLOR]
[COLOR=blue]symbol T22 [/COLOR][COLOR=darkcyan]= [/COLOR][COLOR=navy]199[/COLOR]
[COLOR=blue]symbol T23 [/COLOR][COLOR=darkcyan]= [/COLOR][COLOR=navy]231[/COLOR]
[COLOR=blue]symbol T24 [/COLOR][COLOR=darkcyan]= [/COLOR][COLOR=navy]267[/COLOR]
[COLOR=blue]symbol T25 [/COLOR][COLOR=darkcyan]= [/COLOR][COLOR=navy]299[/COLOR]
[COLOR=blue]symbol T26 [/COLOR][COLOR=darkcyan]= [/COLOR][COLOR=navy]319[/COLOR]
[COLOR=blue]symbol T27 [/COLOR][COLOR=darkcyan]= [/COLOR][COLOR=navy]340 [/COLOR][COLOR=green];or thereabouts?[/COLOR]
[COLOR=blue]symbol T28 [/COLOR][COLOR=darkcyan]= [/COLOR][COLOR=navy]359[/COLOR]
[COLOR=blue]symbol T29 [/COLOR][COLOR=darkcyan]= [/COLOR][COLOR=navy]375 [/COLOR][COLOR=green];or thereabouts[/COLOR]
[COLOR=blue]symbol T30 [/COLOR][COLOR=darkcyan]= [/COLOR][COLOR=navy]399[/COLOR]



[COLOR=black]main:[/COLOR]
[COLOR=blue]READTEMP tempsens[/COLOR][COLOR=black], [/COLOR][COLOR=purple]temperature            [/COLOR][COLOR=green]; read the temperature of DS18B20 on pin c.0, load variable into b1[/COLOR]
[COLOR=blue]debug [/COLOR][COLOR=purple]b1[/COLOR]
[COLOR=blue]serout b.2[/COLOR][COLOR=black], [/COLOR][COLOR=blue]n2400[/COLOR][COLOR=black], [/COLOR][COLOR=blue]( [/COLOR][COLOR=navy]254[/COLOR][COLOR=black], [/COLOR][COLOR=navy]1 [/COLOR][COLOR=blue])                         [/COLOR][COLOR=green]; Clear OLED display[/COLOR]
[COLOR=blue]pause [/COLOR][COLOR=navy]50                                              [/COLOR][COLOR=green]; pause to clear[/COLOR]
[COLOR=blue]serout b.2[/COLOR][COLOR=black], [/COLOR][COLOR=blue]n2400[/COLOR][COLOR=black], [/COLOR][COLOR=blue]( [/COLOR][COLOR=navy]254[/COLOR][COLOR=black], [/COLOR][COLOR=navy]$80 [/COLOR][COLOR=blue])                       [/COLOR][COLOR=green]; First line of display [/COLOR]
[COLOR=blue]serout b.2[/COLOR][COLOR=black], [/COLOR][COLOR=blue]n2400[/COLOR][COLOR=black], [/COLOR][COLOR=blue]( [/COLOR][COLOR=red]"Temperature" [/COLOR][COLOR=blue])                  [/COLOR][COLOR=green]; Display "Temperature" [/COLOR]
[COLOR=blue]serout b.2[/COLOR][COLOR=black], [/COLOR][COLOR=blue]n2400[/COLOR][COLOR=black], [/COLOR][COLOR=blue]( [/COLOR][COLOR=navy]254[/COLOR][COLOR=black], [/COLOR][COLOR=navy]$C0 [/COLOR][COLOR=blue])                       [/COLOR][COLOR=green]; Second line of display [/COLOR]
[COLOR=blue]serout b.2[/COLOR][COLOR=black], [/COLOR][COLOR=blue]n2400[/COLOR][COLOR=black], [/COLOR][COLOR=blue]( [/COLOR][COLOR=black]#[/COLOR][COLOR=purple]temperature[/COLOR][COLOR=black], [/COLOR][COLOR=red]"C" [/COLOR][COLOR=blue])              [/COLOR][COLOR=green]; Display the temperature [/COLOR]
[COLOR=blue]wait [/COLOR][COLOR=navy]2                                    [/COLOR][COLOR=green]; wait 2 seconds                                      [/COLOR]


[COLOR=purple]offset [/COLOR][COLOR=darkcyan]= [/COLOR][COLOR=purple]Temperature [/COLOR][COLOR=darkcyan]MIN [/COLOR][COLOR=navy]20 [/COLOR][COLOR=darkcyan]MAX [/COLOR][COLOR=navy]30 [/COLOR][COLOR=darkcyan]- [/COLOR][COLOR=navy]20               [/COLOR][COLOR=green];returns 0->10[/COLOR]


[COLOR=blue]lookup [/COLOR][COLOR=purple]offset[/COLOR][COLOR=black],[/COLOR][COLOR=blue](T20[/COLOR][COLOR=black],[/COLOR][COLOR=blue]T21[/COLOR][COLOR=black],[/COLOR][COLOR=blue]T22[/COLOR][COLOR=black],[/COLOR][COLOR=blue]T23[/COLOR][COLOR=black],[/COLOR][COLOR=blue]T24[/COLOR][COLOR=black],[/COLOR][COLOR=blue]T25[/COLOR][COLOR=black],[/COLOR][COLOR=blue]T26[/COLOR][COLOR=black],[/COLOR][COLOR=blue]T27[/COLOR][COLOR=black],[/COLOR][COLOR=blue]T28[/COLOR][COLOR=black],[/COLOR][COLOR=blue]T29[/COLOR][COLOR=black],[/COLOR][COLOR=blue]T30)[/COLOR][COLOR=black],[/COLOR][COLOR=purple]PWMCycle[/COLOR]
[COLOR=blue]pwmout B.3[/COLOR][COLOR=black],[/COLOR][COLOR=navy]99[/COLOR][COLOR=black],[/COLOR][COLOR=purple]PWMCycle[/COLOR]
[COLOR=blue]goto [/COLOR][COLOR=black]main                                 [/COLOR][COLOR=green]; return to main[/COLOR]
 
Top