For CCP1CON bits this is much faster
CCP1CON.5=CCPF.1
CCP1CON.4=CCPF.0
For CCP1CON bits this is much faster
CCP1CON.5=CCPF.1
CCP1CON.4=CCPF.0
Thank you Dave and Pedja089 for your input.
I will try implementing your suggestions and report back the results. Unfortunately I just started work so it has to wait for a few good hours.
I was thinking to try something like this subroutine but it was too late last night:
My goal for now is to get enough steps with about 0.25V between them so the TEC will not complain.Code:Set_pwm_pars: CCP1CON.4 = Pwm_pars.0 CCP1CON.5 = Pwm_pars.1 CCPR1L = Pwm_pars >> 2 RETURN Main: FOR i = min_pwm to max_pwm Pwm_pars = i GOSUB Set_pwm_pars PAUSE 250 NEXT PAUSE 5000 GOTO Main
BTW does anyone know if slow, occasional (every few minutes) 0.25V steps combined with heavy capacitor filtering will affect the TEC?
Thanks again for your input.
Nick
Just a quick update: I’ve tried all three suggested methods and they all work as expected.
I will do some more hardware changes, now that I have a stable test code. I will experiment especially with frequency changes and inductors values. I’m trying to get as much efficiency as possible.
What is encouraging though is that running the prototype for long time does not generate heat at all. The main power components are cold and the current draw (from the 12V source) swings between 1A and 2.5A.
I will post the latest working code as soon as I get it cleaned up.
Nick
This is the working code. It steps up through 21 steps of PWM (from 30 to 50) and then steps down (from 50 to 20). The result is an output voltage between 5.5V and 8.5V (the numbers are rounded up). This is design for testing the flexibility of the system only. Final code will implement a temperature controlling algorithm. BTW I switched to PIC16F819 since this is the PIC I'm going to use for this task.
Code based on Dave's input (183):
With the same main loop I changed the subroutine set_pwm_pars based on Pedja089 input (163):Code:@__config_device_pic16f819 @__config_wdt_off @__config_hs_osc @__config_pwrt_on @__config_mclr_off @__config_lvp_off @__config_protect_on @__config_CCP1_RB2 OSCCON=%01110111 DEFINE OSC 8 i var word pwm_out var PORTB.2 pwm_pars var word min_pwm con 30 max_pwm con 50 CCP1CON = %00001100 PR2 = 15 CCPR1L = 0 CCP1CON.5 = 0 CCP1CON.4 =0 High pwm_out Pause 500 Low pwm_out T2CON.2 = 1 goto Main set_pwm_pars: CCPR1L = pwm_pars >> 2 CCP1CON=$0C|((pwm_pars&$3)<<4) RETURN Main: for i=min_pwm to max_pwm pwm_pars = i gosub set_pwm_pars pause 250 next for i=max_pwm to min_pwm step -1 pwm_pars = i gosub set_pwm_pars pause 250 next Pause 5000 Goto Main
Finally my simplified version for the subroutine (187):Code:set_pwm_pars: CCP1CON.5 = pwm_pars.1 CCP1CON.4 = pwm_pars.0 CCPR1L = pwm_pars >> 2 RETURN
The output from all is the same (as expected). Cannot comment on execution speed and for my purposes it doesn’t really matter. I will only set a step, based on the temperature control algorithm, and sit on it for a while. I’m sure that the wine will not mind a few microseconds shifted response.Code:set_pwm_pars: CCP1CON.5 = pwm_pars.1 CCP1CON.4 = pwm_pars.0 CCPR1L = pwm_pars / 4 RETURN
The one difference between the three versions is the code space required. The numbers in parentheses are showing that.
So far I’m happy with my results.
I will work on the hardware for the next few days and start working on the temperature control algorithm after that.
Before I start this new task I’m asking all the people in this forum that might have some experience in this field: Am I on the right track? Is there a better way to do it?
I love its simplicity and the fact that I fully understand how it works but in the same time I hate to find it out that is wrong after I already spent a lot of time on it.
As always looking forward for input.
Nick
The only problem I can see is that you are assuming the other bits in the CCP1CON are always set correctly? For the sacrifice of a few extra instructions I would prefer to have ALL register bits set as in: CCP1CON=$0C|((pwm_pars&$3)<<4)
Dave Purola,
N8NTA
EN82fn
Hi Dave,
You are making a good point. It comes with lock of experience on my side.
As I said before I have two good qualities: learning extremely slow and, in contrast, forgetting extremely fast.
At this point I’m not looking to save program space so I guess playing safe will be a good idea.
Any input on the hardware side?
Nick
I got all the hardware working and wrote a simple temperature control program. Nothing fancy.
The code drives the TEC with different power output levels depending on how far the real temperature is from the set temperature.
I don’t have yet a mechanism of setting the target temperature but this is just to prove that the system works.
Since the major hardware is in place and the cooler is basically functional I will settle for now for a fixed, preprogrammed target temperature.
The ICSP connector for the 16F819 is accessible and I will play with the code to get more features.
I’m forced to take a break from the project but I will get back to it when time permits.
For now 62⁰F should be fine on most of the wines I drink so I’ll make it default.
Anyway it has been a fun weekend project and what makes it special is the fact that I did not have to order any parts. Recycling old junk makes me feel really good.
For all interested below is the simple control code, not fully tested since I just finished it last night. There are few things in the code that are not fully implemented (serial output will be used for a LCD display, hysteresis, id (to diferenciate between the two chambers). These variables will be used for future development when time comes.
Regards,Code:@__config_device_pic16f819 @__config_wdt_off @__config_hs_osc @__config_pwrt_on @__config_mclr_off @__config_lvp_off @__config_protect_on DEFINE OSC 8 DEFINE DEBUG_REG PORTB DEFINE DEBUGIN_REG PORTB DEFINE DEBUG_BIT 6 DEFINE DEBUGIN_BIT 7 DEFINE DEBUG_MODE 1 DEFINE DEBUG_BAUD 38400 DEFINE ADC_BITS 8 DEFINE ADC_CLOCK 3 DEFINE ADC_SAMPLEUS 50 ADCON1=%01001110 pwm_out var PORTB.2 adval var word val_1 var byte val_2 var byte val_3 var byte new var word act_temp var byte set_temp var byte new_temp var byte temp_index var byte i var word pwm_pars var word id var byte start_ch con 126 end_sym con 251 samples con 39 divider con 20 hysteresis con 2 min_pwm con 30 max_pwm con 50 CCP1CON = %00001100 PR2 = 15 CCPR1L = 0 CCP1CON.5 = 0 CCP1CON.4 =0 High pwm_out Pause 500 Low pwm_out T2CON.2 = 1 set_temp=62 goto main send_out: debug start_ch,id,val_1,val_2,val_3,end_sym return set_pwm_pars: CCPR1L = pwm_pars >> 2 CCP1CON=$0C|((pwm_pars&$3)<<4) return read_act_temp: new = 0 For temp_index = 1 TO samples ADCIN 0,adval new = new + adval Next act_temp=new/divider If act_temp <= set_temp then pwm_pars = 0 else pwm_pars = min_pwm+(act_temp - set_temp) if pwm_pars>max_pwm then pwm_pars=max_pwm endif gosub set_pwm_pars val_1=act_temp val_2=pwm_pars val_3=set_temp Return Main: gosub read_act_temp gosub send_out pause 1500 goto Main end
Nick
Bookmarks