PDA

View Full Version : Help with word variable



Scampy
- 26th November 2015, 01:32
Hi Guys,

I've been having a lot of issues with a project to produce a single channel version of a pulse proportional thermostat that uses PID routines developed in conjunction with the Late Darrell Taylor and Henrik back in 2009. Each time I strip the code to remove the unwanted channels from the original 4 channel version it somehow becomes unstable. The 4 channel version has become very large over the years as I've developed it, around 25K with the include files, so I can't (and really don't want to) post the lot up, and as I' wasn't sure where the unsuitability was coming from I've started from scratch, but with the same variables to make porting some parts easier.

I've gone back to basics and started with the reading of a DS18B20 sensor. Rather than use DT's elaborate DT18x20.pbp library file, I've used a simple bit of code that gets the data from the one wire input and places it in the variable TempC

The problem I have is is that the setpoint variable uses three digits to represent the temperature, eg 280 is the setpoint for 28.0C, and when I copied the code over for the PID routine I found the output LED was either on or off and didn't pulse when the temperature came close to the set point. Looking at the code, there is a line that works out the error value by taking the value in the set point for the channel - TempC which is the value read from the sensor. On checking that value, TempC is four digits, so I'm getting something like 2768 for the value of TempC for when the temperature is 27.68 degrees C. So using the formula that results in 280-2768 which results in a negative figure. What I need to do is to make TempC into a 3 digit value, 276, so that when the equation is run I get a positive error, 280-276=4.

Here's the code (minus the PID library's)



'************************************************* ******************************
'* Name : Single ver X.pbp *
'* Author : Malcolm Crabbe. Uses library files from Darrel Taylor *
'* Mentors : *
'* Date : Nov 2015 *
'* Version : *
'* Target : 18F4620 running at 40 Mhz (10 mhz xtal - HS_PLL) *
'* : 1 x DS18x20 *
'************************************************* ******************************


; config settings 18F4620, 10mhz crystal
ASM

__CONFIG _CONFIG1H, _OSC_HSPLL_1H & _FCMEN_OFF_1H & _IESO_OFF_1H
__CONFIG _CONFIG2L, _PWRT_ON_2L & _BOREN_OFF_2L
__CONFIG _CONFIG2H, _WDT_ON_2H & _WDTPS_512_2H
__CONFIG _CONFIG3H, _PBADEN_OFF_3H
__CONFIG _CONFIG4L, _LVP_OFF_4L & _XINST_OFF_4L

ENDASM

DEFINE OSC 40
ADCON1 = $0F
clear

;----[Include Files]------------------------------------------------------------
INCLUDE "incPID_mc.pbp" ' Include the multi-channel PID routine.
PID_Channels CON 1

;----[Port settings]------------------------------------------------------------

CMCON = $07 ' Turn OFF all comparators
ADCON0 = %00000000 ' AD converter module disabled
ADCON1 = %00001111 ' All Digital
ADCON2 = %00000000 '

TRISA = %11000111 ' A0,A1,A2,A6,A7 input A3,A4,A5 output
TRISB = %00000000 ' All output
TRISC = %10010000 ' C0,C1,C2,C3,C5,C6 output, C4 & C7 input
TRISD = %00000001 ' D0 input, D1,D2,D3,D4,D5,D6,D7 output
TRISE = %00000000 ' All output


;----[LCD ]---------------------------------------------------------------------

DEFINE LCD_DREG PORTB ' LCD Data port
DEFINE LCD_DBIT 0 ' starting Data bit (0 or 4)
DEFINE LCD_EREG PORTB ' LCD Enable port
DEFINE LCD_EBIT 5 ' Enable bit (on EasyPIC 5 LCD)
DEFINE LCD_RSREG PORTB ' LCD Register Select port
DEFINE LCD_RSBIT 4 ' Register Select bit (on EasyPIC 5 LCD)
DEFINE LCD_BITS 4 ' LCD bus size (4 or 8 bits)
DEFINE LCD_LINES 4 ' number of lines on LCD
DEFINE LCD_COMMANDUS 2000 ' Command delay time in us
DEFINE LCD_DATAUS 50 ' Data delay time in us

LCDOUT $FE,1:FLAGS=0:PAUSE 250:LCDOUT $FE,1:PAUSE 250 ' Initialize LCD


'----[Pin assignments ]---------------------------------------------------------
TempIn VAR PORTD.0 ' 18b20 data pin
HeaterOut1 VAR PORTD.4 ' Pin assigned to Heater 1

;----[Variables/Aliases - Temperature]------------------------------------------

TempWD VAR WORD ' temporary WORD variable
TempC VAR WORD
Temperatures VAR WORD
SetPoints VAR WORD[1] ' used to store the desired temperature setting
SetPoint1 VAR SetPoints[0]
ChannelPWR VAR BIT
HeatCycle VAR BYTE BANK0 SYSTEM
HeaterDrives VAR BYTE[4] BANK0 SYSTEM ' outputs
HeatDrive1 VAR HeaterDrives[0]
spModes VAR BYTE[1] ' controls how set point is adjusted PC or direct
spMode1 VAR spModes[0]
Bvar VAR BYTE ' temporary BYTE variable

;----[EEPROM Data]-------------------------------------------------------------
DATA @0,0

EE_spMode1 DATA 0 ' 0=Manual mode,
EE_SetPoint1 DATA WORD 280 ' 28.0 deg. after programming if not in manual mode
EE_pid_Kp1 DATA WORD $0700 ' PID constants
EE_pid_Ki1 DATA WORD $0080
EE_pid_Kd1 DATA WORD $0200
EE_pid_Ti1 DATA 8 ' Update I-term every 8th call to PID
EE_pid_I_Clamp1 DATA 125 ' Clamp I-term to max ±100
EE_pid_Out_Clamp1 DATA WORD 255 ' Clamp the final output to 255
EE_CH1PWR DATA 1 ' this needs to be set to 1 to enable heater channel

GOSUB SendPWRstat

DATA @0,0
READ EE_spMode1, spMode1
READ EE_SetPoint1, WORD SetPoint1
READ EE_pid_Kp1, WORD pid_Kp
READ EE_pid_Ki1, WORD pid_Ki
READ EE_pid_Kd1, WORD pid_Kd
READ EE_pid_Ti1, pid_Ti
READ EE_pid_I_Clamp1, pid_I_Clamp
READ EE_pid_Out_Clamp1, WORD pid_Out_Clamp
READ EE_CH1PWR, ChannelPWR(0)

;-------------------------------------------------------------------------------
; ********************* MAIN PROGRAMMING LOOP ************************
;-------------------------------------------------------------------------------

main:

OWOUT TEMPIN,1,[$CC,$44]
HIGH TEMPIN
PAUSE 1000
OWOUT TEMPIN,1,[$CC,$BE]
OWIN TEMPIN,0,[TempWD.LowByte,TEMPWD.HighByte]
TempC = TempWD*/1600
LCDout $FE,1,DEC (TempC/100),".",#TempC dig 1,"C"

pid_Channel = 0

Temperatures(pid_Channel) = TempC
pid_Error = SetPoints(pid_Channel) - TempC
GOSUB PID
IF pid_Out.15 THEN pid_Out = 0 ; only keep positive values
IF ChannelPWR(pid_Channel) THEN
HeaterDrives(pid_Channel) = pid_Out
ELSE
HeaterDrives(pid_Channel) = 0
endif

;----[TMR1 interrupt handler]---------------------------------------------------
ASM
HeaterDrive
incf HeatCycle,F ; HeatCycle

movf _HeatDrive1,W ; HeatDrive1
subwf HeatCycle,w
btfsc STATUS,C
bcf _HeaterOut1
btfss STATUS,C
bsf _HeaterOut1

INT_RETURN
ENDASM

LCDOut $FE, $C0,"Set ",#setpoints(0)dig 2,#setpoints(0)dig 1,$DF,"C"
LCDOut $FE, $D4,"tempC ",dec tempC 'debug only
LCDOut $FE, $D4+14,dec setpoints(0) 'debug only

goto main

SendPWRstat:
Bvar = 0
Bvar.0 = ChannelPWR(0)
RETURN


Any help would be welcome.... it's late and my brain hurts :)

Art
- 26th November 2015, 02:19
So using the formula that results in 280-2768 which results in a negative figure. What I need to do is to make TempC into a 3 digit value, 276, so that when the equation is run I get a positive error, 280-276=4.


Can’t you either divide the 2768 by 10, or multiply the 280 by 10 first?

Scampy
- 26th November 2015, 10:54
Well I did say it was late !

OK that works - and gives a better result for when the current temperature is below the set point, but gives values of 655xx when the curent temp exceeds the setpoint. Also the heatdriver that controlls the LED on port D4 doesn't work as it should. It should be on constant, and then start pulsing at around 1sec frequency as the temperature nears the set point, with the pulse duration getting shorter as the difference between the current temperature and setpoint gets smaller.

I've attached the PID include file hoping someone can advise

richard
- 26th November 2015, 12:16
a pid_out of 65535 would be interpreted as - 1 by your code and therefore ignored


ASM
HeaterDrive
........



you have no code to call this routine
as well as no interrupt code at all that might call it either