module Beaglebone::PWM
PWM
¶ ↑
procedural methods for PWM
control
Summary¶ ↑
start is called to enable a PWM
pin
Constants
- POLARITIES
Polarity hash
Public Class Methods
reset all PWM
pins we’ve used to IN and unexport them
# File lib/beaglebone/pwm.rb, line 286 def cleanup get_pwm_pins.each { |x| disable_pwm_pin(x) } end
Disable a PWM
pin
@param pin should be a symbol representing the header pin
# File lib/beaglebone/pwm.rb, line 303 def disable_pwm_pin(pin) Beaglebone::check_valid_pin(pin, :pwm) Beaglebone::delete_pin_status(pin) if Beaglebone::device_tree_unload("#{TREES[:PWM][:pin]}#{pin}") end
Returns true if specified pin is enabled in PWM
mode, else false
# File lib/beaglebone/pwm.rb, line 73 def enabled?(pin) return true if Beaglebone::get_pin_status(pin, :type) == :pwm return false unless valid?(pin) if Dir.exists?(pwm_directory(pin)) start(pin, nil, nil, nil, false) return true end false end
Return an array of PWM
pins in use
@return [Array<Symbol>]
@example
PWM.get_pwm_pins => [:P9_13, :P9_14]
# File lib/beaglebone/pwm.rb, line 296 def get_pwm_pins Beaglebone.pinstatus.clone.select { |x,y| x if y[:type] == :pwm}.keys end
Start PWM
output on specified pin. Pin must have been previously started
@param pin should be a symbol representing the header pin
# File lib/beaglebone/pwm.rb, line 109 def run(pin) Beaglebone::check_valid_pin(pin, :pwm) return false unless enabled?(pin) raise StandardError, "Pin is not PWM enabled: #{pin}" unless Beaglebone::get_pin_status(pin, :type) == :pwm run_fd = Beaglebone::get_pin_status(pin, :fd_run) raise StandardError, "Pin is not PWM enabled: #{pin}" unless run_fd run_fd.write('1') run_fd.flush raise StandardError, "Could not start PWM: #{pin}" unless read_run_value(pin) == 1 true end
Set duty cycle of specified pin in percentage
@param pin should be a symbol representing the header pin @param duty should specify the duty cycle in percentage @example
PWM.set_duty_cycle(:P9_14, 25)
# File lib/beaglebone/pwm.rb, line 154 def set_duty_cycle(pin, duty, newperiod=nil) raise ArgumentError, "Duty cycle must be >= 0 and <= 100, #{duty} invalid" if duty < 0 || duty > 100 check_pwm_enabled(pin) fd = Beaglebone::get_pin_status(pin, :fd_duty) raise StandardError, "Pin is not PWM enabled: #{pin}" unless fd period = newperiod || Beaglebone::get_pin_status(pin, :period) value = ((duty * period) / 100.0).round fd.write(value.to_s) fd.flush raise StandardError, "Could not set duty cycle: #{pin} (#{value})" unless read_duty_value(pin) == value Beaglebone::set_pin_status(pin, :duty_pct, duty) value end
Set duty cycle of specified pin in nanoseconds
@param pin should be a symbol representing the header pin @param duty should specify the duty cycle in nanoseconds @example
PWM.set_duty_cycle_ns(:P9_14, 2500000)
# File lib/beaglebone/pwm.rb, line 184 def set_duty_cycle_ns(pin, duty) check_pwm_enabled(pin) fd = Beaglebone::get_pin_status(pin, :fd_duty) raise StandardError, "Pin is not PWM enabled: #{pin}" unless fd period = Beaglebone::get_pin_status(pin, :period) duty = duty.to_i if duty < 0 || duty > period raise ArgumentError, "Duty cycle ns must be >= 0 and <= #{period} (current period), #{duty} invalid" end value = duty fd.write(value.to_s) fd.flush #since we're setting the duty_ns, we want to update the duty_pct value as well here. raise StandardError, "Could not set duty cycle: #{pin} (#{value})" unless read_duty_value(pin, true) == value value end
Set frequency of specified pin in cycles per second
@param pin should be a symbol representing the header pin @param frequency should specify the frequency in cycles per second @example
PWM.set_frequency(:P9_14, 100)
# File lib/beaglebone/pwm.rb, line 216 def set_frequency(pin, frequency) frequency = frequency.to_i raise ArgumentError, "Frequency must be > 0 and <= 1000000000, #{frequency} invalid" if frequency < 1 || frequency > 1000000000 check_pwm_enabled(pin) fd = Beaglebone::get_pin_status(pin, :fd_period) raise StandardError, "Pin is not PWM enabled: #{pin}" unless fd duty_ns = Beaglebone::get_pin_status(pin, :duty) duty_pct = Beaglebone::get_pin_status(pin, :duty_pct) value = (1000000000 / frequency).round #we can't set the frequency lower than the previous duty cycle #adjust if necessary if duty_ns > value set_duty_cycle(pin, Beaglebone::get_pin_status(pin, :duty_pct), value) end fd.write(value.to_s) fd.flush raise StandardError, "Could not set frequency: #{pin} (#{value})" unless read_period_value(pin) == value #adjust the duty cycle if we haven't already if duty_ns <= value set_duty_cycle(pin, duty_pct, value) end value end
Set frequency of specified pin based on period duration
@param pin should be a symbol representing the header pin @param period should specify the length of a cycle in nanoseconds
@example
PWM.set_frequency_ns(:P9_14, 100000000)
# File lib/beaglebone/pwm.rb, line 255 def set_period_ns(pin, period) period = period.to_i raise ArgumentError, "period must be > 0 and <= 1000000000, #{period} invalid" if period < 1 || period > 1000000000 check_pwm_enabled(pin) fd = Beaglebone::get_pin_status(pin, :fd_period) raise StandardError, "Pin is not PWM enabled: #{pin}" unless fd duty_ns = Beaglebone::get_pin_status(pin, :duty) value = period.to_i #we can't set the frequency lower than the previous duty cycle #adjust if necessary if duty_ns > value set_duty_cycle(pin, Beaglebone::get_pin_status(pin, :duty_pct), value) end fd.write(value.to_s) fd.flush raise StandardError, "Could not set period: #{pin} (#{value})" unless read_period_value(pin) == value #adjust the duty cycle if we haven't already if duty_ns <= value set_duty_cycle(pin, Beaglebone::get_pin_status(pin, :duty_pct), value) end value end
Set polarity on specified pin
@param pin should be a symbol representing the header pin @param polarity should specify the polarity, :NORMAL or :INVERTED @example
PWM.set_polarity(:P9_14, :INVERTED)
# File lib/beaglebone/pwm.rb, line 134 def set_polarity(pin, polarity) check_valid_polarity(polarity) check_pwm_enabled(pin) polarity_fd = Beaglebone::get_pin_status(pin, :fd_polarity) raise StandardError, "Pin is not PWM enabled: #{pin}" unless polarity_fd polarity_fd.write(POLARITIES[polarity.to_sym].to_s) polarity_fd.flush raise StandardError, "Could not set polarity: #{pin}" unless read_polarity_value(pin) == POLARITIES[polarity.to_sym] end
Initialize a PWM
pin
@param pin should be a symbol representing the header pin @param duty should specify the duty cycle @param frequency should specify cycles per second @param polarity optional, should specify the polarity, :NORMAL or :INVERTED @param run optional, if false, pin will be configured but will not run
@example
PWM.start(:P9_14, 90, 10, :NORMAL)
# File lib/beaglebone/pwm.rb, line 25 def start(pin, duty=nil, frequency=nil, polarity=nil, run=true) #make sure the pwm controller dtb is loaded Beaglebone::device_tree_load(TREES[:PWM][:global]) Beaglebone::check_valid_pin(pin, :pwm) #if pin is enabled for something else, disable it if Beaglebone::get_pin_status(pin) && Beaglebone::get_pin_status(pin, :type) != :pwm Beaglebone::disable_pin(pin) end #load device tree for pin if not already loaded unless Beaglebone::get_pin_status(pin, :type) == :pwm Beaglebone::device_tree_load("#{TREES[:PWM][:pin]}#{pin}", 0.5) Beaglebone::set_pin_status(pin, :type, :pwm) end duty_fd = File.open("#{pwm_directory(pin)}/duty", 'r+') period_fd = File.open("#{pwm_directory(pin)}/period", 'r+') polarity_fd = File.open("#{pwm_directory(pin)}/polarity", 'r+') run_fd = File.open("#{pwm_directory(pin)}/run", 'r+') Beaglebone::set_pin_status(pin, :fd_duty, duty_fd) Beaglebone::set_pin_status(pin, :fd_period, period_fd) Beaglebone::set_pin_status(pin, :fd_polarity, polarity_fd) Beaglebone::set_pin_status(pin, :fd_run, run_fd) read_period_value(pin) read_duty_value(pin) read_polarity_value(pin) run_fd.write('0') run_fd.flush set_polarity(pin, polarity) if polarity set_frequency(pin, frequency) if frequency set_duty_cycle(pin, duty) if duty if run run_fd.write('1') run_fd.flush end raise StandardError, "Could not start PWM: #{pin}" unless read_run_value(pin) == 1 true end
Stop PWM
output on specified pin
@param pin should be a symbol representing the header pin
# File lib/beaglebone/pwm.rb, line 88 def stop(pin) Beaglebone::check_valid_pin(pin, :pwm) return false unless enabled?(pin) raise StandardError, "Pin is not PWM enabled: #{pin}" unless Beaglebone::get_pin_status(pin, :type) == :pwm run_fd = Beaglebone::get_pin_status(pin, :fd_run) raise StandardError, "Pin is not PWM enabled: #{pin}" unless run_fd run_fd.write('0') run_fd.flush raise StandardError, "Could not stop PWM: #{pin}" unless read_run_value(pin) == 0 true end
Private Class Methods
ensure pin is pwm enabled
# File lib/beaglebone/pwm.rb, line 322 def check_pwm_enabled(pin) raise StandardError, "Pin is not PWM enabled: #{pin}" unless enabled?(pin) end
ensure polarity is valid
# File lib/beaglebone/pwm.rb, line 393 def check_valid_polarity(polarity) #check to see if mode is valid polarity = polarity.to_sym raise ArgumentError, "No such polarity: #{polarity.to_s}" unless POLARITIES.include?(polarity) end
return sysfs directory for pwm control
# File lib/beaglebone/pwm.rb, line 387 def pwm_directory(pin) raise StandardError, 'Invalid Pin' unless valid?(pin) Dir.glob("/sys/devices/ocp.*/pwm_test_#{pin}.*").first end
read duty file
# File lib/beaglebone/pwm.rb, line 352 def read_duty_value(pin, setpct=false) check_pwm_enabled(pin) fd = Beaglebone::get_pin_status(pin, :fd_duty) raise StandardError, "Pin is not PWM enabled: #{pin}" unless fd fd.rewind value = fd.read.strip.to_i Beaglebone::set_pin_status(pin, :duty, value) # only set duty_pct if it is unset or if we are forcing it. if setpct || Beaglebone::get_pin_status(pin, :duty_pct).nil? duty_pct = ((value * 100.0) / Beaglebone::get_pin_status(pin, :period)).round Beaglebone::set_pin_status(pin, :duty_pct, duty_pct) end value end
read period file
# File lib/beaglebone/pwm.rb, line 372 def read_period_value(pin) check_pwm_enabled(pin) fd = Beaglebone::get_pin_status(pin, :fd_period) raise StandardError, "Pin is not PWM enabled: #{pin}" unless fd fd.rewind value = fd.read.strip.to_i Beaglebone::set_pin_status(pin, :period, value) value end
read polarity file
# File lib/beaglebone/pwm.rb, line 338 def read_polarity_value(pin) check_pwm_enabled(pin) fd = Beaglebone::get_pin_status(pin, :fd_polarity) raise StandardError, "Pin is not PWM enabled: #{pin}" unless fd fd.rewind value = fd.read.strip.to_i Beaglebone::set_pin_status(pin, :polarity, value) end
read run file
# File lib/beaglebone/pwm.rb, line 327 def read_run_value(pin) check_pwm_enabled(pin) fd = Beaglebone::get_pin_status(pin, :fd_run) raise StandardError, "Pin is not PWM enabled: #{pin}" unless fd fd.rewind fd.read.strip.to_i end
ensure pin is valid pwm pin
# File lib/beaglebone/pwm.rb, line 311 def valid?(pin) #check to see if pin exists pin = pin.to_sym return false unless PINS[pin] return false unless PINS[pin][:pwm] true end