1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
extern crate tessel;
use std::io;
use std::thread;
use std::time::Duration;
use std::ops::Range;
#[repr(u8)]
#[allow(dead_code)]
#[derive(Copy, Clone)]
enum Command {
MODE1 = 0x0,
LED0_ON_L = 0x06,
LED0_ON_H = 0x07,
LED0_OFF_L = 0x08,
LED0_OFF_H = 0x09,
PRESCALE = 0xFE,
}
const MAX: u16 = 4096;
const I2C_ID: u8 = 0x73;
#[allow(dead_code)]
pub struct ServoArray<'a> {
i2c: tessel::I2cPort<'a>,
addr2: tessel::Pin<'a>,
addr3: tessel::Pin<'a>,
output_enable: tessel::Pin<'a>,
range: Range<f64>,
i2c_id: u8,
}
impl<'a> ServoArray<'a> {
pub fn new<'b>(port: tessel::Port, addr2: bool, addr3: bool) -> ServoArray<'b> {
let (i2c, gpio) = port.i2c();
let (addr2, addr3, output_enable) = gpio.pin_select((5, 6, 7));
ServoArray {
i2c: i2c,
addr2: addr2,
addr3: addr3,
output_enable: output_enable,
range: 0.0..1.0,
i2c_id: I2C_ID,
}
}
pub fn connect(&mut self) -> io::Result<()> {
self.output_enable.output(false);
self.addr2.output(false);
self.addr3.output(false);
self.set_module_frequency(50);
Ok(())
}
pub fn set_module_frequency(&mut self, frequency: u64) {
let prescale: u8 = (((25000000 / (MAX as u64)) / frequency) - 1) as u8;
let mut buf = [0; 1];
self.i2c.transfer(self.i2c_id, &[Command::MODE1 as u8], &mut buf);
let mode = buf[0];
self.i2c.send(self.i2c_id, &[Command::MODE1 as u8, mode | 0x10]);
self.i2c.send(self.i2c_id, &[Command::PRESCALE as u8, prescale]);
self.i2c.send(self.i2c_id, &[Command::MODE1 as u8, mode]);
self.i2c.send(self.i2c_id, &[Command::MODE1 as u8, 0xA1]);
}
pub fn set_duty_cycle(&mut self, i: usize, value: f64) {
let offset = ((i - 1) * 4) as u8;
let reg = (((MAX - 1) as f64) * f64::max(f64::min(value, 1.0), 0.0)) as u16;
println!("0 0 {:?} {:?}", (reg & 0xFF) as u8, ((reg >> 8) & 0xFF) as u8);
self.i2c.send(self.i2c_id, &[Command::LED0_ON_L as u8 + offset, 0]);
self.i2c.send(self.i2c_id, &[Command::LED0_ON_H as u8 + offset, 0]);
self.i2c.send(self.i2c_id, &[Command::LED0_OFF_L as u8 + offset, (reg & 0xFF) as u8]);
self.i2c.send(self.i2c_id, &[Command::LED0_OFF_H as u8 + offset, ((reg >> 8) & 0xFF) as u8]);
}
}