Docs

Software Code:

1 # analog_in.py

2 # This file declares a class to use analog GPIO pins as inputs

3

4

5 # importing libraries

6 import Adafruit_BBIO.ADC as ADC

7

8

9 class Analog_In:

10

11    def __init__(self, pin):

12        # pin: dictionary containing used input pin

13        self.sig = pin["ain"]

14        ADC.setup()

15

16    def read(self):

17        # function: read normalized analog value

18        # function returns: float number from 0.0 to 1.0

19        return ADC.read(self.sig)

20

21    def read_raw(self):

22        # function: read raw analog value

23        # function returns: float number from 0.0 to 4095.0

24        return ADC.read_raw(self.sig)

1 # config.py

2 # This file list all used pins for blood smearing device

3 # Note: please leave pin labels alone, other files depend on those specific labels

4

5

6 # active output pins for linear guide

7 # "ena": digital LOW enables pulses to be sent

8 #        digital HIGH disables pulses

9 # "dir": digital LOW for ccw rotation

10 #        digital HIGH for cw rotation

11 # "pul": digital HIGH then LOW turns motor one step

12 slide_pins = {"ena": "P8_11", "dir": "P8_15", "pul": "P8_17"}

13

14 # active digital input pin for home (opposite side of stepper motor) limit switch

15 limit_home_pin = {"sig": "P9_11"}

16

17 # active digital input pin for end (same side as stepper motor) limit switch

18 limit_end_pin = {"sig": "P9_12"}

19

20 # active digital output pin for activating drying fan

21 fan_pin = {"sig": "P8_16"}

22

23 # active output pulse pin for blade ejection linear servo

24 linear_pin = {"pul": "P9_14"}  # 6V

25

26 # active output pulse pin for blade ejection pulley servo

27 pulley_pin = {"pul": "P9_16"}  # 6V

28

29 # active output pulse pin for blade ejection rotation servo

30 rotation_pin = {"pul": "P8_19"}  # 6V

31

32 # active output power and input analog pins for force sensor

33 force_pins = {"sig": "P8_21", "ain": "P9_33"}

 1 # digital_io.py

 2 # This file declares a class to use digital GPIO pins as inputs/outputs

 3

 4

 5 # importing libraries

 6 import Adafruit_BBIO.GPIO as GPIO

 7 import numpy as np

 8 import time

 9

10

11 class Digital_Io:

12

13    # class initialization also initializes pin

14    def __init__(self, pin, direction, value=None):

15        # pin: dictionary containing used input/output pin

16        # direction: string "in" to set up pin as an input or

17        #            string "out" to set up pin as an output

18        # value: int 0 for initial LOW output or

19        #        int 1 for initial HIGH output

20        self.sig = pin["sig"]

21        if direction == "in":

22            self.dir = GPIO.IN

23            GPIO.setup(self.sig, self.dir)

24        elif direction == "out":

25            self.dir = GPIO.OUT

26            if value == 0:

27                GPIO.setup(self.sig, self.dir, initial=GPIO.LOW)

28            elif value == 1:

29                GPIO.setup(self.sig, self.dir, initial=GPIO.HIGH)

30            else:

31                print("\nError: Invalid value input")

32        else:

33            print("\nError: Invalid string direction input (\"in\" or \"out\"")

34            print("\"in\" for input pin or \"out\" for output pin")

35            print("Please include quotation marks")

36

37    def read(self):

38        # function: read input voltage as HIGH or LOW

39        # function returns: int 0 when nothing is detected and

40        #                   int 1 when sensor is triggered

41        return GPIO.input(self.sig)

42

43    def output(self, value):

44        # function: output 3.3V or 0V

45        # value: int 0 outputs 0V or

46        #        int 1 outputs 3.3V

47        if value == 0:

48            GPIO.output(self.sig, GPIO.LOW)

49        elif value == 1:

50            GPIO.output(self.sig, GPIO.HIGH)

51        else:

52            print("\nError: Invalid value input")

53

54    def add_event(self, edge):

55        # function: add event detection

56        # edge: string "rise" to detect rising edge

57        #       string "fall" to detect falling edge

58        #       string "both" to detect both edges

59        if edge == "rise":

60            self.edge = GPIO.RISING

61            GPIO.add_event_detection(self.sig, self.edge)

62        elif edge == "fall":

63            self.edge = GPIO.FALLING

64            GPIO.add_event_detection(self.sig, self.edge)

65        elif edge == "both":

66            self.edge = GPIO.BOTH

67            GPIO.add_event_detection(self.sig, self.edge)

68        else:

69            print("Error: Invalid string edge input")

70            print("\"rise\" for rising edge")

71            print("\"fall\" for falling edge")

72            print("\"both\" for both edges")

73            print("Please add quotation marks")

74

75    def event(self):

76        # function: detect event

77        # function returns: bool True if edge is detected or

78        #                   bool False otherwise

79        return GPIO.event_detected(self.sig)

80

81    def wait(self):

82        # function: wait for event

83        GPIO.wait_for_edge(self.sig, self.edge)

84

85    def remove_event(self):

86        # function: remove event detection

87        GPIO.remove_event_detect(self.sig)

88

89    def read2(self, num_samples, correct_samples, frequency):

90        # function: read input by many samples

91        # num_samples: int number of samples

92        # correct_samples: int number of correct samples

93        # frequency: float number sampling rate in [Hz]

94        # function returns: bool True if read input is correct

95        #                   bool False if read input is incorrect

96        num_samples = int(num_samples)

97        correct_samples = int(correct_samples)

98        if correct_samples > num_samples:

99            print("Error: correct_samples cannot be higher than num_samples")

100        samples = np.array([0] * num_samples)

101        sleepTime = float(1 / frequency)

102        for i in range(num_samples):

103            samples[i] = self.read()

104            time.sleep(sleepTime)

105        if np.sum(samples) >= correct_samples:

106            return True

107        else:

108            return False

109

110    def cleanup(self):

111        # function: clean up pin

112        GPIO.remove_event_detect(self.sig)

113        GPIO.cleanup()

1 # servo.py

2 # This file declares a class to use any servo motor

3

4

5 # importing libraries

6 import Adafruit_BBIO.PWM as PWM

7 import time

8

9

10 class Servo:

11

12    def __init__(self, pin, angle_range=180):

13        # pin: dictionary containing used servo PWM pin

14        # angle_range: float number describing the max angle range of a servo

15        #              motor [degrees], by default 180 degrees

16        self.pul = pin["pul"]

17        self.range = angle_range

18

19    def start(self, duty_min, duty_max, frequency=50, polarity=0):

20        # function: start/initialize servo

21        # duty_min: float PWM duty cycle for 0 [degrees]

22        # duty_max: float PWM duty cycle for angle range [degrees]

23        # frequency: float PWM frequency [Hz], must be > 0, by default 50Hz

24        # polarity: int defines whether the duty affects the PWM waveform

25        #           by default 0 (rising edge), 1 (falling edge)

26        self.min = float(duty_min)

27        self.max = float(duty_max)

28        self.span = duty_max - duty_min

29        duty = self.min

30        PWM.start(self.pul, duty, frequency, polarity)

31

32    def update_duty(self, duty):

33        # function: change servo duty cycle

34        # duty: float PWM duty cycle from 0-100

35        PWM.set_duty_cycle(self.pul, duty)

36

37    def update_angle(self, angle):

38        # function: set servo angle

39        # angle: float servo angle from (0, max) [degrees]

40        duty = angle * self.span / self.range + self.min

41        self.update_duty(duty)

42

43    def change_angle(self, start, end, time2turn=2):

44        # function: move servo from a start angle to an end angle

45        # start: float number for starting angle position [degrees]

46        # end: float number for ending angle position [degrees]

47        # time2turn: float number for total time for servo to move

48        diff = abs(end - start)

49        time_sleep = time2turn / diff

50        if end > start:

51            angle = start

52            while angle <= end:

53                self.update_angle(angle)

54                time.sleep(time_sleep)

55                angle += 1

56        else:

57            angle = end

58            while angle >= start:

59                self.update_angle(angle)

60                time.sleep(time_sleep)

61                angle -= 1

62

63    def disable(self):

64        # function: disable servo motor

65        PWM.stop(self.pul)

66

67    def cleanup(self):

68        # function: cleanup servo PWM pin

69        PWM.stop(self.pul)

70        PWM.cleanup()

1 # stepper.py

 2 # This file declares a class to use any stepper motor

 3

 4

 5 # importing libraries

 6 import Adafruit_BBIO.GPIO as GPIO

 7 import time

 8 from math import pi

 9

10

11 class Stepper:

12

13    # class initialization also initializes motor

14    def __init__(self, pins, circumference, microstep=8):

15        # pins: dictionary containing used stepper motor pins

16        # circumference: float number for distance traveled by one motor

17        #                revolution

18        # microstep: int number for current microstep configuration for

19        #            stepper motor, by default microstep is 8

20        self.ena = pins["ena"]

21        self.dir = pins["dir"]

22        self.pul = pins["pul"]

23        self.circum = circumference

24        self.radius = self.circum / (pi * 2)

25        self.mms2rpm = 30 / (self.radius * pi)

26        self.micro = microstep

27        if microstep == 1:

28            self.pulses = 200    # 1 micro step = 200 pulses

29        elif microstep == 2:

30            self.pulses == 400   # 2 micro steps = 400 pulses

31        elif microstep == 4:

32            self.pulses = 800    # 4 micro steps = 800 pulses

33        elif microstep == 8:

34            self.pulses = 1600   # 8 micro steps = 1600 pulses

35        elif microstep == 10:

36            self.pulses = 2000   # 10 micro steps = 2000 pulses

37        elif microstep == 16:

38            self.pulses = 3200   # 16 micro steps = 3200 pulses

39        elif microstep == 32:

40            self.pulses = 6400   # 32 micro steps = 6400 pulses

41        else:

42            print("Error: Invalid micro step value")

43        GPIO.setup(self.pul, GPIO.OUT, initial=GPIO.LOW)

44        GPIO.setup(self.dir, GPIO.OUT)

45        GPIO.setup(self.ena, GPIO.OUT, initial=GPIO.LOW)

46

47    def step(self):

48        # function: step motor

49        GPIO.output(self.pul, GPIO.HIGH)

50

51    def stop(self):

52        # function: stop stepping motor

53        GPIO.output(self.pul, GPIO.LOW)

54

55    def set_direction(self, direction):

56        # function: set motor rotation direction

57        # direction: string "cw" for clockwise rotation or

58        #            string "ccw" for counter-clockwise rotation

59        if direction == "cw":

60            GPIO.output(self.dir, GPIO.HIGH)

61        elif direction == "ccw":

62            GPIO.output(self.dir, GPIO.LOW)

63        else:

64            print(

65                "Error: Invalid direction sting [\"cw\" for cw or \"ccw\" for ccw]")

66            print("Please include quotation marks")

67

68    def convert_mms2rpm(self, mms):

69        # function: convert linear velocity [mm/s] to rotational velocity [rpm]

70        # mms: float number of motor load's linear velocity [mm/s]

71        # function return: float number to motor's rotational velocity [rpm]

72        return (mms * self.mms2rpm)

73

74    def rotate(self, rotations, rpm, direction):

75        # function: move motor by rotations

76        # rotations: float number of motor rotations

77        # rpm: float number of motor's rpm

78        # direction: string "cw" for clockwise or

79        #            string "ccw" for counter-clockwise

80        sleep_time = float(0.3 * 1.34 / (rpm * self.micro))

81        steps = round(rotations * self.pulses)

82        if direction == "cw":

83            GPIO.output(self.dir, GPIO.HIGH)

84            for x in range(steps):

85                self.step()

86                time.sleep(sleep_time)

87                GPIO.output(self.pul, GPIO.LOW)

88        elif direction == "ccw":

89            GPIO.output(self.dir, GPIO.LOW)

90            for x in range(steps):

91                self.step()

92                time.sleep(sleep_time)

93                GPIO.output(self.pul, GPIO.LOW)

94        else:

95            print(

96                "Error: Invalid direction sting [\"cw\" for cw or \"ccw\" for ccw]")

97            print("Please include quotation marks")

98

99    def move_steps(self, numberOfSteps, rpm, direction):

100        # function: move motor by amount of steps

101        # numberOfSteps: int number of steps motor will turn

102        # rpm: float number of motor's rpm

103        # direction: string "cw" for clockwise or

104        #            string "ccw" for counter-clockwise

105        rotations = numberOfSteps / self.pulses

106        self.rotate(rotations, rpm, direction)

107

108    def move_linear(self, distance, rpm, direction):

109        # function: move motor with respect to linear load distance

110        # distance: float number of motor's linear distance to travel [mm]

111        # rpm: float number of motor's rpm [rpm]

112        # direction: string "cw" for clockwise or

113        #            string "ccw" for counter-clockwise

114        rotations = distance / self.circum

115        self.rotate(rotations, rpm, direction)

116

117    def disable_pulse(self):

118        # function: disable motor from sending pulses

119        GPIO.output(self.ena, GPIO.HIGH)

120

121    def enable_pulse(self):

122        # function: enable motor to send pulses

123        GPIO.output(self.ena, GPIO.LOW)

124

125    def cleanup(self):

126        # function: cleanup up pins from use

127        self.disable_pulse()

128        GPIO.cleanup()

PCB Circuit Traces: