├── FIR.py ├── LICENSE ├── MAX31865.py ├── MAX31885.py ├── MAX6675.py ├── PDM.py ├── PID.py ├── SPI.py ├── lcd.py ├── main.py ├── robocam ├── .DS_Store ├── .idea │ ├── .name │ ├── encodings.xml │ ├── misc.xml │ ├── modules.xml │ ├── robocam.iml │ ├── scopes │ │ └── scope_settings.xml │ ├── vcs.xml │ └── workspace.xml ├── main.py └── pyboard │ └── main.py └── rotary.py /FIR.py: -------------------------------------------------------------------------------- 1 | __author__ = 'beau' 2 | 3 | import array 4 | class FIR(): 5 | """ 6 | Finit impulse response filter, aka moving average. 7 | """ 8 | def __init__(self, window_size=30,div=1): 9 | self.div = div 10 | self.win_size = window_size 11 | self.a = array.array('l', window_size * [0]) # no double on pyboard? integers logic for now 12 | self.arr_position = 0 13 | self.sum = 0 14 | 15 | def push(self, value): 16 | old_val = self.a[self.arr_position] 17 | self.a[self.arr_position] = value 18 | self.arr_position += 1 19 | self.arr_position %= self.win_size 20 | self.sum -= old_val 21 | self.sum += value 22 | 23 | def get_value(self): 24 | return self.sum / self.win_size / self.div 25 | 26 | def median(self): 27 | return sorted(self.a)[int(self.win_size/2)] 28 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | GNU LESSER GENERAL PUBLIC LICENSE 2 | Version 3, 29 June 2007 3 | 4 | Copyright (C) 2007 Free Software Foundation, Inc. 5 | Everyone is permitted to copy and distribute verbatim copies 6 | of this license document, but changing it is not allowed. 7 | 8 | 9 | This version of the GNU Lesser General Public License incorporates 10 | the terms and conditions of version 3 of the GNU General Public 11 | License, supplemented by the additional permissions listed below. 12 | 13 | 0. Additional Definitions. 14 | 15 | As used herein, "this License" refers to version 3 of the GNU Lesser 16 | General Public License, and the "GNU GPL" refers to version 3 of the GNU 17 | General Public License. 18 | 19 | "The Library" refers to a covered work governed by this License, 20 | other than an Application or a Combined Work as defined below. 21 | 22 | An "Application" is any work that makes use of an interface provided 23 | by the Library, but which is not otherwise based on the Library. 24 | Defining a subclass of a class defined by the Library is deemed a mode 25 | of using an interface provided by the Library. 26 | 27 | A "Combined Work" is a work produced by combining or linking an 28 | Application with the Library. The particular version of the Library 29 | with which the Combined Work was made is also called the "Linked 30 | Version". 31 | 32 | The "Minimal Corresponding Source" for a Combined Work means the 33 | Corresponding Source for the Combined Work, excluding any source code 34 | for portions of the Combined Work that, considered in isolation, are 35 | based on the Application, and not on the Linked Version. 36 | 37 | The "Corresponding Application Code" for a Combined Work means the 38 | object code and/or source code for the Application, including any data 39 | and utility programs needed for reproducing the Combined Work from the 40 | Application, but excluding the System Libraries of the Combined Work. 41 | 42 | 1. Exception to Section 3 of the GNU GPL. 43 | 44 | You may convey a covered work under sections 3 and 4 of this License 45 | without being bound by section 3 of the GNU GPL. 46 | 47 | 2. Conveying Modified Versions. 48 | 49 | If you modify a copy of the Library, and, in your modifications, a 50 | facility refers to a function or data to be supplied by an Application 51 | that uses the facility (other than as an argument passed when the 52 | facility is invoked), then you may convey a copy of the modified 53 | version: 54 | 55 | a) under this License, provided that you make a good faith effort to 56 | ensure that, in the event an Application does not supply the 57 | function or data, the facility still operates, and performs 58 | whatever part of its purpose remains meaningful, or 59 | 60 | b) under the GNU GPL, with none of the additional permissions of 61 | this License applicable to that copy. 62 | 63 | 3. Object Code Incorporating Material from Library Header Files. 64 | 65 | The object code form of an Application may incorporate material from 66 | a header file that is part of the Library. You may convey such object 67 | code under terms of your choice, provided that, if the incorporated 68 | material is not limited to numerical parameters, data structure 69 | layouts and accessors, or small macros, inline functions and templates 70 | (ten or fewer lines in length), you do both of the following: 71 | 72 | a) Give prominent notice with each copy of the object code that the 73 | Library is used in it and that the Library and its use are 74 | covered by this License. 75 | 76 | b) Accompany the object code with a copy of the GNU GPL and this license 77 | document. 78 | 79 | 4. Combined Works. 80 | 81 | You may convey a Combined Work under terms of your choice that, 82 | taken together, effectively do not restrict modification of the 83 | portions of the Library contained in the Combined Work and reverse 84 | engineering for debugging such modifications, if you also do each of 85 | the following: 86 | 87 | a) Give prominent notice with each copy of the Combined Work that 88 | the Library is used in it and that the Library and its use are 89 | covered by this License. 90 | 91 | b) Accompany the Combined Work with a copy of the GNU GPL and this license 92 | document. 93 | 94 | c) For a Combined Work that displays copyright notices during 95 | execution, include the copyright notice for the Library among 96 | these notices, as well as a reference directing the user to the 97 | copies of the GNU GPL and this license document. 98 | 99 | d) Do one of the following: 100 | 101 | 0) Convey the Minimal Corresponding Source under the terms of this 102 | License, and the Corresponding Application Code in a form 103 | suitable for, and under terms that permit, the user to 104 | recombine or relink the Application with a modified version of 105 | the Linked Version to produce a modified Combined Work, in the 106 | manner specified by section 6 of the GNU GPL for conveying 107 | Corresponding Source. 108 | 109 | 1) Use a suitable shared library mechanism for linking with the 110 | Library. A suitable mechanism is one that (a) uses at run time 111 | a copy of the Library already present on the user's computer 112 | system, and (b) will operate properly with a modified version 113 | of the Library that is interface-compatible with the Linked 114 | Version. 115 | 116 | e) Provide Installation Information, but only if you would otherwise 117 | be required to provide such information under section 6 of the 118 | GNU GPL, and only to the extent that such information is 119 | necessary to install and execute a modified version of the 120 | Combined Work produced by recombining or relinking the 121 | Application with a modified version of the Linked Version. (If 122 | you use option 4d0, the Installation Information must accompany 123 | the Minimal Corresponding Source and Corresponding Application 124 | Code. If you use option 4d1, you must provide the Installation 125 | Information in the manner specified by section 6 of the GNU GPL 126 | for conveying Corresponding Source.) 127 | 128 | 5. Combined Libraries. 129 | 130 | You may place library facilities that are a work based on the 131 | Library side by side in a single library together with other library 132 | facilities that are not Applications and are not covered by this 133 | License, and convey such a combined library under terms of your 134 | choice, if you do both of the following: 135 | 136 | a) Accompany the combined library with a copy of the same work based 137 | on the Library, uncombined with any other library facilities, 138 | conveyed under the terms of this License. 139 | 140 | b) Give prominent notice with the combined library that part of it 141 | is a work based on the Library, and explaining where to find the 142 | accompanying uncombined form of the same work. 143 | 144 | 6. Revised Versions of the GNU Lesser General Public License. 145 | 146 | The Free Software Foundation may publish revised and/or new versions 147 | of the GNU Lesser General Public License from time to time. Such new 148 | versions will be similar in spirit to the present version, but may 149 | differ in detail to address new problems or concerns. 150 | 151 | Each version is given a distinguishing version number. If the 152 | Library as you received it specifies that a certain numbered version 153 | of the GNU Lesser General Public License "or any later version" 154 | applies to it, you have the option of following the terms and 155 | conditions either of that published version or of any later version 156 | published by the Free Software Foundation. If the Library as you 157 | received it does not specify a version number of the GNU Lesser 158 | General Public License, you may choose any version of the GNU Lesser 159 | General Public License ever published by the Free Software Foundation. 160 | 161 | If the Library as you received it specifies that a proxy can decide 162 | whether future versions of the GNU Lesser General Public License shall 163 | apply, that proxy's public statement of acceptance of any version is 164 | permanent authorization for you to choose that version for the 165 | Library. 166 | 167 | -------------------------------------------------------------------------------- /MAX31865.py: -------------------------------------------------------------------------------- 1 | __author__ = 'beau' 2 | import pyb 3 | import SPI 4 | import math 5 | import FIR 6 | 7 | 8 | class MAX31865(): 9 | def __init__(self,DRDY_pin='X9'): 10 | self.spi = SPI.SPI() 11 | self.fir = FIR.FIR(16) 12 | 13 | """ 14 | Configuration bits: 15 | Vbias 1=on 16 | Conversion mode 1=auto,0=normally off 17 | 1-shot 1=1-shot (auto-clear) 18 | 3-wire 1=3-wire,0=2/4 wire 19 | Fault detection 20 | Fault detection 21 | Fault Status 1=clear 22 | Filter 1=50Hz,2=60Hz 23 | """ 24 | 25 | config = 0b11000011 26 | 27 | buf = bytearray(2) 28 | buf[0] = 0x80 #configuration write addr 29 | buf[1] = config 30 | self.spi.write(buf) 31 | 32 | self.RefR = 100.0325 #RefR/2 33 | 34 | self.last_read_time = 0 35 | self.last_read_temp = 0 36 | self.last_FIR = 0 37 | 38 | 39 | self.conversion_time = 22 #21ms for 50Hz, 17.6 for 60Hz 40 | 41 | 42 | def _RawToTemp(self,raw): 43 | R0 = raw/(1<<15)*200 44 | R0 = R0/self.RefR*100 45 | if R0==0: 46 | return -1,0 47 | #ITS-90 IEC751 Pt-100 coefficients 48 | A = 3.90830e-3 49 | B = -5.77500e-7 50 | return (A - math.sqrt(A*A - 4*B*(1-100/R0) ) ) / (2*B),R0 51 | 52 | def read(self): 53 | if pyb.millis()-self.last_read_time > self.conversion_time: 54 | temp,avg_temp = self._read() 55 | self.last_read_temp = temp 56 | self.last_FIR = avg_temp 57 | return self.last_read_temp,self.last_FIR 58 | 59 | 60 | def _read(self): 61 | 62 | #read config 63 | #config = self.spi.read(0x00,1)[0] 64 | #print ("Config:"+str(bin(config)[2:])) 65 | 66 | #read data 67 | MSB = self.spi.read(0x01,1)[0] 68 | LSB = self.spi.read(0x02,1)[0] 69 | 70 | MSB = MSB<<8 71 | raw = MSB+LSB 72 | raw = raw>>1 #remove fault bit 73 | 74 | 75 | 76 | 77 | self.fir.push(raw) 78 | temp,R0 = self._RawToTemp(raw) 79 | avg_temp,avg_R0 = self._RawToTemp(self.fir.median()) 80 | 81 | return temp,avg_temp 82 | 83 | -------------------------------------------------------------------------------- /MAX31885.py: -------------------------------------------------------------------------------- 1 | __author__ = 'beau' 2 | 3 | import pyb 4 | from FIR import FIR 5 | 6 | class MAX31885(): 7 | 8 | def __init__(self,CS_pin='Y5',SO_pin='Y7',SCK_pin='Y6'): 9 | #Thermocouple 10 | self.CS_pin = pyb.Pin(CS_pin, pyb.Pin.OUT_PP) 11 | self.CS_pin.high() 12 | 13 | self.SO_pin = pyb.Pin(SO_pin, pyb.Pin.IN) 14 | self.SO_pin.low() 15 | 16 | self.SCK_pin = pyb.Pin(SCK_pin, pyb.Pin.OUT_PP) 17 | self.SCK_pin.low() 18 | 19 | self.last_read_time = 0 20 | self.last_read_room_temp = 0 21 | self.last_read_tc_temp = 0 22 | self.fault = 0 23 | self.open_circuit = 0 24 | self.short_to_gnd = 0 25 | self.short_to_vcc = 0 26 | 27 | self.FIR = FIR(window_size=16,div=8) 28 | 29 | 30 | def read(self): 31 | # self.CS_pin.low() 32 | # pyb.delay(2) 33 | # self.CS_pin.high() 34 | # pyb.delay(220) 35 | 36 | #check if new reading should be available 37 | #if True: 38 | if pyb.millis()-self.last_read_time > 100: 39 | 40 | #/* 41 | # Bring CS pin low to allow us to read the data from 42 | # the conversion process 43 | #*/ 44 | self.CS_pin.low() 45 | 46 | # 47 | # Read bits D[31:18] for the Temp. Loop for each bit reading 48 | # the value and storing the final value in 'temp' 49 | # 50 | tc_temp = 0 51 | 52 | self.SCK_pin.high() 53 | sign = self.SO_pin.value() 54 | self.SCK_pin.low() 55 | for i in range(13): 56 | self.SCK_pin.high() 57 | read = self.SO_pin.value() 58 | read = (read << 13 - i) 59 | tc_temp += read 60 | self.SCK_pin.low() 61 | if sign == 1: 62 | tc_temp*=-1 63 | self.FIR.push(tc_temp) 64 | tc_temp/=8.0 65 | 66 | 67 | 68 | # D17 dummy 69 | self.SCK_pin.high() 70 | pyb.delay(1) 71 | self.SCK_pin.low() 72 | 73 | # D16 fault 74 | self.SCK_pin.high() 75 | self.fault = self.SO_pin.value() 76 | self.SCK_pin.low() 77 | 78 | 79 | # D15-D4 80 | # Roomtemp, signed 81 | self.SCK_pin.high() 82 | sign = self.SO_pin.value() 83 | self.SCK_pin.low() 84 | room_temp = 0 85 | for i in range(11): 86 | self.SCK_pin.high() 87 | read = self.SO_pin.value() 88 | read = (read << 11 - i) 89 | room_temp += read 90 | self.SCK_pin.low() 91 | if sign == 1: 92 | room_temp*=-1 93 | room_temp/=32.0 94 | 95 | # D3 dummy 96 | self.SCK_pin.high() 97 | pyb.delay(1) 98 | self.SCK_pin.low() 99 | 100 | # D2 fault 101 | self.SCK_pin.high() 102 | self.short_to_vcc = self.SO_pin.value() 103 | self.SCK_pin.low() 104 | 105 | # D1 fault 106 | self.SCK_pin.high() 107 | self.short_to_gnd = self.SO_pin.value() 108 | self.SCK_pin.low() 109 | 110 | # D0 fault 111 | self.SCK_pin.high() 112 | self.open_circuit = self.SO_pin.value() 113 | self.SCK_pin.low() 114 | 115 | 116 | 117 | self.CS_pin.high() 118 | 119 | 120 | self.last_read_time = pyb.millis() 121 | self.last_read_room_temp = room_temp 122 | self.last_read_tc_temp = tc_temp 123 | 124 | 125 | return tc_temp,room_temp 126 | 127 | #to soon for new reading 128 | else: 129 | return self.last_read_tc_temp,self.last_read_room_temp -------------------------------------------------------------------------------- /MAX6675.py: -------------------------------------------------------------------------------- 1 | __author__ = 'beau' 2 | 3 | import pyb 4 | from FIR import FIR 5 | 6 | class MAX6675(): 7 | 8 | def __init__(self,CS_pin='Y8',SO_pin='Y7',SCK_pin='Y6'): 9 | #Thermocouple 10 | self.CS_pin = pyb.Pin(CS_pin, pyb.Pin.OUT_PP) 11 | self.CS_pin.high() 12 | 13 | self.SO_pin = pyb.Pin(SO_pin, pyb.Pin.IN) 14 | self.SO_pin.low() 15 | 16 | self.SCK_pin = pyb.Pin(SCK_pin, pyb.Pin.OUT_PP) 17 | self.SCK_pin.low() 18 | 19 | self.last_read_time = 0 20 | self.last_read_temp = 0 21 | self.last_error_tc = 0 22 | 23 | self.FIR = FIR(20) 24 | 25 | 26 | def read(self): 27 | # self.CS_pin.low() 28 | # pyb.delay(2) 29 | # self.CS_pin.high() 30 | # pyb.delay(220) 31 | 32 | #check if new reading should be available 33 | #if True: 34 | if pyb.millis()-self.last_read_time > 220: 35 | 36 | #/* 37 | # Bring CS pin low to allow us to read the data from 38 | # the conversion process 39 | #*/ 40 | self.CS_pin.low() 41 | 42 | #/* Cycle the clock for dummy bit 15 */ 43 | self.SCK_pin.high() 44 | pyb.delay(1) 45 | self.SCK_pin.high() 46 | 47 | #/* 48 | # Read bits 14-3 from MAX6675 for the Temp. Loop for each bit reading 49 | # the value and storing the final value in 'temp' 50 | # */ 51 | value = 0 52 | for i in range(12): 53 | self.SCK_pin.high() 54 | read = self.SO_pin.value() 55 | read = (read << 12 - i) 56 | value += read 57 | self.SCK_pin.low() 58 | 59 | 60 | #/* Read the TC Input inp to check for TC Errors */ 61 | self.SCK_pin.high() 62 | error_tc = self.SO_pin.value() 63 | self.SCK_pin.low() 64 | 65 | # /* 66 | # Read the last two bits from the chip, faliure to do so will result 67 | # in erratic readings from the chip. 68 | # */ 69 | for i in range(2): 70 | self.SCK_pin.high() 71 | pyb.delay(1) 72 | self.SCK_pin.low() 73 | 74 | self.CS_pin.high() 75 | 76 | self.FIR.push(value) 77 | temp = (value * 0.25) 78 | self.last_read_time = pyb.millis() 79 | self.last_read_temp = temp 80 | self.last_error_tc = error_tc 81 | 82 | return temp,error_tc 83 | 84 | #to soon for new reading 85 | else: 86 | return self.last_read_temp,self.last_error_tc -------------------------------------------------------------------------------- /PDM.py: -------------------------------------------------------------------------------- 1 | __author__ = 'beau' 2 | 3 | import pyb 4 | 5 | class PDM(): 6 | def __init__(self,pout='X11',tim=4,freq=50): 7 | """ 8 | :param pout: output pin nr 9 | :param tim: timer number 10 | :param freq: frequency of the bitstream 11 | """ 12 | self.max = 2**24-1#2**31-1 crashes with larger ints? 24bit resolution is fine enough ;) 13 | 14 | self.pout = pyb.Pin(pout, pyb.Pin.OUT_PP) 15 | 16 | self.err = 0 # error accumulator 17 | self.output = 0 18 | 19 | self.freq = freq 20 | 21 | self.tim = pyb.Timer(tim) 22 | self.tim.init(freq=freq) 23 | self.tim.callback(lambda t: self.call_me()) 24 | 25 | def set_output(self,out): 26 | """ 27 | :param out: desired output as a value between 0 and 1 28 | """ 29 | print ('setting output to '+str(out)) 30 | self.tim.deinit() 31 | 32 | self.output = int(self.max*out) 33 | 34 | self.tim.init(freq=self.freq) 35 | self.tim.callback(lambda t: self.call_me()) 36 | 37 | def call_me(self): 38 | if self.err >= 0: 39 | self.pout.low() 40 | self.err -= self.output 41 | else: 42 | self.pout.high() 43 | self.err += self.max 44 | self.err -= self.output -------------------------------------------------------------------------------- /PID.py: -------------------------------------------------------------------------------- 1 | __author__ = 'beau' 2 | import pyb 3 | class PID: 4 | """ 5 | Discrete PID control 6 | """ 7 | 8 | def __init__(self,input_fun,output_fun, P=3., I=0.01, D=0.0): 9 | 10 | self.Kp=P 11 | self.Ki=I 12 | self.Kd=D 13 | 14 | self.I_value = 0 15 | self.P_value = 0 16 | self.D_value = 0 17 | 18 | self.I_max=100.0 19 | self.I_min=0 20 | 21 | self.set_point=0.0 22 | 23 | self.prev_value = 0 24 | 25 | self.output = 0 26 | 27 | self.output_fun = output_fun 28 | self.input_fun = input_fun 29 | 30 | self.last_update_time = pyb.millis() 31 | 32 | 33 | def update(self): 34 | 35 | if pyb.millis()-self.last_update_time > 500: 36 | """ 37 | Calculate PID output value for given reference input and feedback 38 | """ 39 | current_value = self.input_fun() 40 | self.error = self.set_point - current_value 41 | print ('temp '+str(current_value)) 42 | print ('SP'+str(self.set_point)) 43 | 44 | self.P_value = self.Kp * self.error 45 | self.D_value = self.Kd * ( current_value-self.prev_value) 46 | 47 | 48 | lapsed_time = pyb.millis()-self.last_update_time 49 | lapsed_time/=1000. #convert to seconds 50 | self.last_update_time = pyb.millis() 51 | 52 | 53 | 54 | 55 | 56 | self.I_value += self.error * self.Ki 57 | 58 | if self.I_value > self.I_max: 59 | self.I_value = self.I_max 60 | elif self.I_value < self.I_min: 61 | self.I_value = self.I_min 62 | 63 | self.output = self.P_value + self.I_value - self.D_value 64 | 65 | if self.output<0: 66 | self.output = 0.0 67 | if self.output>100: 68 | self.output = 100.0 69 | 70 | print("Setpoint: "+str(self.set_point)) 71 | print("P: "+str(self.P_value)) 72 | print("I: "+str(self.I_value)) 73 | print("Output: "+str(self.output)) 74 | print () 75 | 76 | self.output_fun(self.output/100.0) 77 | 78 | self.last_update_time=pyb.millis() 79 | -------------------------------------------------------------------------------- /SPI.py: -------------------------------------------------------------------------------- 1 | __author__ = 'beau' 2 | 3 | import pyb 4 | 5 | class SPI(): 6 | def __init__(self,CS_pin='X10',SCK_pin='Y6',MISO_pin='Y7',MOSI_pin='Y8',delay=10): 7 | self.CS = pyb.Pin(CS_pin, pyb.Pin.OUT_PP) 8 | self.CS.high() 9 | 10 | self.MISO = pyb.Pin(MISO_pin,pyb.Pin.IN) 11 | self.MOSI = pyb.Pin(MOSI_pin,pyb.Pin.OUT_PP) 12 | 13 | self.SCK = pyb.Pin(SCK_pin, pyb.Pin.OUT_PP) 14 | self.delay = delay 15 | 16 | 17 | 18 | def write(self,data): 19 | self.CS.low() 20 | pyb.udelay(self.delay) 21 | self._write(data) 22 | self.CS.high() 23 | 24 | def read(self,read_addr,nr_bytes): 25 | buf = bytearray(1) 26 | buf[0]=read_addr 27 | self.CS.low() 28 | pyb.udelay(self.delay) 29 | self._write(buf) 30 | result = self._read(nr_bytes) 31 | self.CS.high() 32 | return result 33 | 34 | def _read(self,nr_bytes): 35 | buf = bytearray(nr_bytes) 36 | 37 | for b in range(nr_bytes): 38 | byte = 0 39 | for i in range(8): 40 | self.SCK.high() 41 | pyb.udelay(self.delay) 42 | read = self.MISO.value() 43 | read = (read << 8 - i) 44 | byte += read 45 | self.SCK.low() 46 | pyb.udelay(self.delay) 47 | buf[b]=byte 48 | 49 | return buf 50 | 51 | def _write(self,data): 52 | msb = 0b10000000 53 | 54 | for byte in data: 55 | bits = [(byte< 2 | 3 | 4 | -------------------------------------------------------------------------------- /robocam/.idea/misc.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /robocam/.idea/modules.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /robocam/.idea/robocam.iml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /robocam/.idea/scopes/scope_settings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | -------------------------------------------------------------------------------- /robocam/.idea/vcs.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /robocam/.idea/workspace.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 14 | 15 | 16 | 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 | 56 | 57 | 58 | 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 | 92 | 93 | 94 | 95 | 98 | 99 | 102 | 103 | 104 | 105 | 108 | 109 | 112 | 113 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | 134 | 135 | 136 | 137 | 155 | 156 | 179 | 180 | 200 | 201 | 217 | 218 | 239 | 240 | 258 | 259 | 277 | 278 | 279 | 280 | 281 | 282 | 283 | 284 | 285 | 286 | 287 | 288 | 289 | 290 | 291 | 292 | 293 | 1424467678102 294 | 297 | 298 | 299 | 300 | 301 | 302 | 303 | 304 | 305 | 306 | 307 | 308 | 309 | 310 | 311 | 312 | 313 | 314 | 315 | 316 | 317 | 318 | 319 | 320 | 321 | 322 | 323 | 324 | 325 | 328 | 331 | 332 | 333 | 335 | 336 | 339 | 340 | 341 | 342 | 343 | 344 | 345 | 346 | 347 | 348 | 349 | 350 | 351 | 352 | 353 | 354 | 355 | 356 | 357 | 358 | 359 | 360 | 361 | 362 | 363 | 364 | 365 | 366 | 367 | 368 | 369 | 370 | 371 | 372 | 373 | 374 | 375 | 376 | 377 | 378 | 379 | 380 | 381 | 382 | 383 | 384 | 385 | 386 | 387 | 388 | 389 | 390 | 391 | 392 | 393 | 394 | -------------------------------------------------------------------------------- /robocam/main.py: -------------------------------------------------------------------------------- 1 | __author__ = 'beau' 2 | import serial 3 | ser = serial.Serial('/dev/tty.usbmodem1422',9600, timeout=1) 4 | import time 5 | import sys 6 | 7 | def get_angle(): 8 | print "requesting angle" 9 | start = time.time() 10 | 11 | ser.write('nofddfp\n') 12 | print "..." 13 | reply = ser.readline() 14 | deltaT = time.time()-start 15 | print reply 16 | print "round-trip time {}".format(deltaT) 17 | sys.stdout.flush() 18 | 19 | while True: 20 | get_angle() 21 | print "-------------" 22 | 23 | #time.sleep(0.1) -------------------------------------------------------------------------------- /robocam/pyboard/main.py: -------------------------------------------------------------------------------- 1 | import pyb 2 | usb = pyb.USB_VCP() 3 | 4 | # servo1 = pyb.Servo(1) 5 | # servo2 = pyb.Servo(2) 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | def main_loop(): 14 | while True: 15 | r = usb.readline() 16 | #usb.write("message received ") 17 | if r==b'angle': 18 | # X = servo1.angle() 19 | # Y = servo2.angle() 20 | # result = str(X)+" "+str(Y) 21 | usb.write("angle\n") 22 | 23 | else: 24 | usb.write(str(r)) 25 | usb.write(" error\n") 26 | 27 | #pyb.delay(10) 28 | 29 | 30 | main_loop() -------------------------------------------------------------------------------- /rotary.py: -------------------------------------------------------------------------------- 1 | __author__ = 'beau' 2 | import pyb 3 | 4 | class rotary(): 5 | 6 | def __init__(self,Apin='X21',Bpin='X22'): 7 | self.B = pyb.Pin(Bpin) 8 | self.A = pyb.Pin(Apin) 9 | 10 | self.prevA = self.A.value() 11 | self.prevB = self.B.value() 12 | 13 | self.CWcount = 0 14 | self.CCWcount = 0 15 | 16 | self.position = 0 17 | 18 | self.Bint = pyb.ExtInt(self.B,pyb.ExtInt.IRQ_RISING_FALLING,pyb.Pin.PULL_UP,self.callback) 19 | self.Aint = pyb.ExtInt(self.A,pyb.ExtInt.IRQ_RISING_FALLING,pyb.Pin.PULL_UP,self.callback) 20 | 21 | 22 | self.init = True 23 | 24 | def callback(self,line): 25 | if self.init: 26 | self.Bint.disable() 27 | self.Aint.disable() 28 | 29 | 30 | A = self.A.value() 31 | B = self.B.value() 32 | 33 | #previous state 11 34 | if self.prevA==1 and self.prevB==1: 35 | if A==1 and B==0: 36 | #print( "CCW 11 to 10") 37 | self.CCWcount += 1 38 | self.prevA = A 39 | self.prevB = B 40 | 41 | elif A==0 and B==0: 42 | #print ("CW 11 to 00") 43 | self.CWcount += 1 44 | self.prevA = A 45 | self.prevB = B 46 | 47 | #previous state 10 48 | elif self.prevA==1 and self.prevB==0: 49 | if A==1 and B==1: 50 | #print ("CW 10 to 11") 51 | self.CWcount += 1 52 | self.prevA = A 53 | self.prevB = B 54 | 55 | elif A==0 and B==0: 56 | #print ("CCW 10 to 00") 57 | self.CCWcount += 1 58 | self.prevA = A 59 | self.prevB = B 60 | 61 | #previous state 00 62 | elif self.prevA==0 and self.prevB==0: 63 | if A==1 and B==1: 64 | #print ("CCW 00 to 11") 65 | self.CCWcount += 1 66 | self.prevA = A 67 | self.prevB = B 68 | 69 | elif A==1 and B==0: 70 | #print ("CW 00 to 10") 71 | self.CWcount+=1 72 | self.prevA = A 73 | self.prevB = B 74 | 75 | if self.init: 76 | self.Bint.enable() 77 | self.Aint.enable() 78 | 79 | if A==1 and B==1: 80 | if self.CWcount>=3 and self.CWcount>self.CCWcount: 81 | self.position-=1 82 | if self.CCWcount>=3 and self.CCWcount>self.CWcount: 83 | self.position+=1 84 | self.CCWcount = 0 85 | self.CWcount = 0 86 | 87 | 88 | 89 | 90 | 91 | --------------------------------------------------------------------------------