Revision: 1487 Author: eur.van.andel Date: Thu Nov 19 15:09:18 2009 Log: added period_skipping motor control lib + sample
http://code.google.com/p/jallib/source/detail?r=1487 Added: /trunk/include/external/motor/period_skip /trunk/include/external/motor/period_skip/period_skip.jal ======================================= --- /dev/null +++ /trunk/include/external/motor/period_skip/period_skip.jal Thu Nov 19 15:09:18 2009 @@ -0,0 +1,179 @@ +-- Title: motor speed control by skipping periods of AC mains +-- Author: Eur van Andel, [email protected] (c) 2009 +-- Compiler: >=2.4g +-- +-- This file is part of jallib (http://jallib.googlecode.com) +-- Released under the ZLIB license (http://www.opensource.org/licenses/zlib-license.html) + +-- Description: AC induction motors are low-priced, very reliable and widely available. +-- This library provides a way to control the speed of these motors, if they have reasonably +-- angular momentum. + +-- Explanation: this is *NOT* phase control: http://en.wikipedia.org/wiki/Phase_control +-- Phase control makes a lot of noise, both audible and electrical. + +-- This is deliberate skipping of half-waves. There are only 100 half-waves per second +-- @ 50 Hz and bit-fine control of motor speed would result in long duty cycles (2.55s) +-- with varying motor speeds and audible pitch change. +-- So we keep the period cycle at 32 half waves, with 8 duty cycles that only differ +-- one half-wave to minimise audible noise. +-- Electrical noise is minimized by zero-voltage switching. + +-- Sources: +-- Fairchild Application Note AN-3004, http://www.fairchildsemi.com/an/AN/AN-3004.pdf +-- http://www.sullivan-county.com/ele/triacs2.htm for schematics and examples how +-- to generate a zero-crossing signal. + + +-- speed duty cycle on duty cycle off +-- +-- 0 0 0 0 0 0 0 0 0 32 32 32 32 32 32 32 32 +-- 1 1 0 0 0 0 0 0 0 31 32 32 32 32 32 32 32 +-- 2 1 0 0 0 1 0 0 0 31 32 32 32 31 32 32 32 +-- 3 1 0 0 1 0 0 1 0 31 32 32 31 32 32 31 32 +-- 4 1 0 1 0 1 0 1 0 31 32 31 32 31 32 31 32 +-- 5 1 0 1 0 1 1 0 1 31 32 31 32 31 31 32 31 +-- 6 1 1 0 1 1 0 1 1 31 31 32 31 31 32 31 31 +-- 7 1 1 0 1 1 1 1 1 31 31 32 31 31 31 31 31 +-- 8 1 1 1 1 1 1 1 1 31 31 31 31 31 31 31 31 +-- +-- 9 2 1 1 1 1 1 1 1 30 31 31 31 31 31 31 31 + +-- all the way to 255: + +-- 255 32 32 31 32 32 32 32 32 0 0 1 0 0 0 0 0 + +-- Since 256 would be full speed. At 255 the motor misses one half wave every 2.55 seconds, +-- which is 99.6% of full speed. + + +-- Requirements: + +-- 1) output pin labeled "triac", connected to a TRIAC, for instance via a MOC3042 +-- zero-crossing opto-isolated triac driver, so that the TRIAC is on when the pin is high. + +-- 2) zero-crossing interrupt pin (B0), rising where mains voltage is zero, for instance +-- with an HPCL354 optocoupler and a 10k pullup resistor. + +-- 3) byte variable labeled "speed" with value ranging from 0...255 + +-- 4) if speed changes, the procedure adjust_period() should be called + +-- 5) check_period() should be called at least every 320 ms, not once a month :-) +-- for 60 Hz mains frequency, call this procedure at least every 266 ms + +-- var bit triac is pin_a0 -- pin connected to optotriac +-- pin_a0_direction = output +-- pin_b0_direction = input +-- var byte speed = 0 -- 0..255 speed control, should be declared in main app + +var byte counter -- 1..32 ISR period counter + -- 32 periods to minimise noise +var byte total_duty_cycle -- position in total duty cycle + +var byte on_period = 0 +var byte on_1, on_2, on_3, on_4, on_5, on_6, on_7, on_8 + +INTCON_INTE = on -- pin_b0 rising edge +INTCON_GIE = on -- check if your PIC has these interrupt enable bits + + +-- start procedures -------------------------------------------------- + +procedure RTC() is +pragma interrupt -- every 10ms, triggered by zero-cross + INTCON_INTF = false + if counter > on_period then + triac = off + else + triac = on + end if + counter = counter + 1 + if counter == 33 then + counter = 1 + end if + total_duty_cycle = total_duty_cycle + 1 +end procedure + + +procedure adjust_period() is +var byte div8, mod8 + div8 = speed/8 + mod8 = speed % 8 + on_1 = div8 + on_2 = div8 + on_3 = div8 + on_4 = div8 + on_5 = div8 + on_6 = div8 + on_7 = div8 + on_8 = div8 + if mod8 == 0 then + return + elsif mod8 == 1 then + on_1 = on_1 + 1 + return + elsif mod8 == 2 then + on_1 = on_1 + 1 + on_4 = on_4 + 1 + return + elsif mod8 == 3 then + on_1 = on_1 + 1 + on_4 = on_4 + 1 + on_7 = on_7 + 1 + return + elsif mod8 == 4 then + on_1 = on_1 + 1 + on_3 = on_3 + 1 + on_5 = on_5 + 1 + on_7 = on_7 + 1 + return + elsif mod8 == 5 then + on_1 = on_1 + 1 + on_3 = on_3 + 1 + on_5 = on_5 + 1 + on_6 = on_6 + 1 + on_8 = on_8 + 1 + return + elsif mod8 == 6 then + on_1 = on_1 + 1 + on_2 = on_2 + 1 + on_4 = on_4 + 1 + on_5 = on_5 + 1 + on_6 = on_6 + 1 + on_8 = on_8 + 1 + return + elsif mod8 == 7 then + on_1 = on_1 + 1 + on_2 = on_2 + 1 + on_4 = on_4 + 1 + on_5 = on_5 + 1 + on_6 = on_6 + 1 + on_7 = on_7 + 1 + on_8 = on_8 + 1 + return + end if +end procedure + + + +procedure check_period() is -- should be called every 320 ms @ 50 Hz! + if total_duty_cycle < 32 then -- counting from 0 to 255 + on_period = on_1 + elsif total_duty_cycle > 32 then + on_period = on_2 + elsif total_duty_cycle > 64 then + on_period = on_3 + elsif total_duty_cycle > 96 then + on_period = on_4 + elsif total_duty_cycle > 128 then + on_period = on_5 + elsif total_duty_cycle > 160 then + on_period = on_6 + elsif total_duty_cycle > 192 then + on_period = on_7 + elsif total_duty_cycle > 224 then + on_period = on_8 + end if +end procedure + -- You received this message because you are subscribed to the Google Groups "jallib" group. To post to this group, send email to [email protected]. To unsubscribe from this group, send email to [email protected]. For more options, visit this group at http://groups.google.com/group/jallib?hl=.
