リストの通りに自動運転させる

測定するモジュールを作る



Buttonsモジュール(ButtonLed.fs)
module Buttons
    open System
    open System.Timers
    open System.Threading
    open RaspberryPiDotNet
    let SW = [| new GPIOMem(GPIOPins.V2Plus_Pin_P1_38);
                new GPIOMem(GPIOPins.V2Plus_Pin_P1_37);
                new GPIOMem(GPIOPins.V2Plus_Pin_P1_40)|]
    for i = 0 to SW.Length-1 do
        SW.[i].PinDirection <- GPIODirection.In

    let value n = SW.[n].Read() 
    let waitButton() =
        let mutable on = true
        let mutable n = -1
        while on=true do
            for i = 0 to SW.Length-1 do
                if SW.[i].Read() = PinState.Low then 
                    on <- false
                    n <- i
                    Thread.Sleep(100)
        n
    let LED = [|new GPIOMem(GPIOPins.V2_Pin_P1_22)
                new GPIOMem(GPIOPins.V2_Pin_P1_18)
                new GPIOMem(GPIOPins.V2_Pin_P1_16)
                new GPIOMem(GPIOPins.V2_Pin_P1_12)|]
    for i = 0 to SW.Length-1 do
        LED.[i].PinDirection <- GPIODirection.Out
    let Write (n, state:PinState) = 
        LED.[n].Write(state) 
    let clear() =
        for i=0 to LED.Length-1 do
            LED.[i].Write(PinState.Low)
 1 Buttonsモジュール
 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 


Roboモジュール

両輪のステッピングモーターを制御するモジュール
Roboモジュール(Wheel.fs)
module Robo
    open System
    open System.Timers
    open System.Threading
    open RaspberryPiDotNet

    let Wait n =            // 時間稼ぎ
        let mutable a=0
        while a<n do
            a <- a+1

    type ShareData () =
        member val StopFlag : bool = false with get, set
        member val TotalTime : int = 0 with get, set
  
    type SteppingMotor (clockPin : GPIOPins, cwPin : GPIOPins, dir : bool, bnk : ShareData) =
        let clock = new GPIOMem(clockPin)
        let cw    = new GPIOMem(cwPin)
        static let mutable motor = null 
        let direction = dir
        let mutable numberOfTimes = 0
        let mutable sleepTime = 0
        let bank = bnk
        do
            if motor=null then 
                motor <- new GPIOMem(GPIOPins.V2Plus_Pin_P1_29)
                motor.PinDirection <- GPIODirection.Out
            clock.PinDirection <- GPIODirection.Out
            cw.PinDirection <- GPIODirection.Out
            clock.Write(false)
            cw.Write(direction)
        member val oneStep = 4.75*Math.PI/400.0 with get
        member this.Move() =
             bank.StopFlag <- false
             let mutable sp = 0
             let each = 10
             let step = sleepTime
             let last = numberOfTimes - each - 2
             for i = 0 to numberOfTimes do
                 if not bank.StopFlag then
                    clock.Write(true)
                    if i<each then sp <- each - i
                    elif last < i then sp <- i - last+step
                    else sp <- step
                    Wait(1000)
                    clock.Write(false)
                    Thread.Sleep(sp)
             bank.StopFlag <- true
        member this.Start (sleep) =
            sleepTime <- (int)sleep
            if sleepTime >= 0 then cw.Write(direction)
            else cw.Write(not direction)
            sleepTime <- Math.Abs(sleepTime)
            numberOfTimes <-(int)((float)bank.TotalTime/(float)sleepTime+0.5)
            let thread = new Thread(new ThreadStart(this.Move))
            bank.StopFlag<-false
            thread.Start()
         member this.MotorOn() =
             motor.Write(true)
         member this.MotorOff() =
             motor.Write(false)
            
    type BasicWheel() =
        let forward = true
        let bank = new ShareData()
        let motorR = new SteppingMotor(GPIOPins.V2Plus_Pin_P1_33, GPIOPins.V2Plus_Pin_P1_31, forward, bank)
        let motorL = new SteppingMotor(GPIOPins.V2Plus_Pin_P1_32, GPIOPins.V2Plus_Pin_P1_36, not forward, bank)
        let WaitTime = 300
        member this.move(pathway:float, step:int) =    // cm unit
            bank.TotalTime <- (int)(Math.Abs((float)step) *(pathway / motorR.oneStep + 0.5))
            motorR.MotorOn()
            motorR.Start(step)
            motorL.Start(step)
            while not bank.StopFlag do Thread.Sleep(1)
            motorR.MotorOff()
            Thread.Sleep(WaitTime)
        member this.move(step:int) =
            this.move(400.0,step)
        member this.rotate(deg, stp)=
                let mutable dir = false
                let mutable degree = deg
                let mutable step : int = stp
                if degree < 0 then
                    dir <- true
                    degree <- -degree
                let pathway = Math.PI*9.8/360.0*(float)degree        // outside size of wheels
                step <- Math.Abs (step)
                bank.TotalTime <- step * (int)(pathway / motorR.oneStep + 0.5)
                motorR.MotorOn()
                if dir=true then
                    motorR.Start (step)
                    motorL.Start (-step)
                else
                    motorR.Start (-step)
                    motorL.Start (step)
                while not bank.StopFlag do Thread.Sleep(1)
                motorR.MotorOff()
                Thread.Sleep(WaitTime)
        member this.turn(Rt:int, Lt:int, pathway:float) =
                let step = Math.Max (Math.Abs (Rt), Math.Abs (Lt))
                bank.TotalTime <- step * (int)(pathway / motorR.oneStep + 0.5)
                motorR.MotorOn ()
                motorR.Start(Rt)
                motorL.Start (Lt)
                while not bank.StopFlag do Thread.Sleep(1)
                motorR.MotorOff()
                Thread.Sleep(WaitTime)
 1 Roboモジュール
 2 
 3 
 4 
 5 
 6 
 7 
 8 
 9 
10 
11 
12 
13 
14 
15 
16 SteppingMotorクラス
17 
18 
19 
20 
21 
22 
23 
24 
25 
26 
27 
28 
29 
30 
31 
32 
33 Moveメソッド
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 BasicWheelクラス
64 
65 
66 
67 
68 
69 moveメソッド
70 
71 
72 
73 
74 
75 
76 
77 
78 
79 rotateメソッド
80 
81 
82 
83 
84 
85 
86 
87 
88 
89 
90 
91 
92 
93 
94 
95 
96 
97 
98 
99 turnメソッド
100 
101
102
103 
104 
105 
106 
107 


メインプログラム



main.fs
(*
sw0 かsw1を押すと開始
sw2を押すと終了

*)
open System
open System.Threading
open Buttons
open Robo

let bw = new BasicWheel()
let ReadWay filename = 
  let dat = System.IO.File.ReadAllLines filename
  let rowlen = Array.length dat
  for i = 0 to rowlen-1 do
    let label = dat.[i].Split([|' '|])
    if label.Length>1 then
        let f x y z p =
            match x with
            | "turn" -> bw.turn(y,z,p)
            | "straight" -> bw.move((float)y,1) 
            | "rotate" -> bw.rotate(y,1)
            | "sleep" -> Thread.Sleep(int y) 
            | _ -> printfn "nop "
        let  m = Int32.Parse(label.[1])
        let mutable n = 0
        let mutable p = 0.0
        try
          n <- Int32.Parse(label.[2])
          p <- Double.Parse(label.[3])
        with
            | _ ->  n <- 0
        printf "%s " label.[0]
        f label.[0] m n p

[<EntryPoint>]
let main argv =
    let mutable Continue = true     // 続けて実行するか
    while Continue do
        let n = waitButton()
        if n = 2 then 
           Continue <- false
        else 
            ReadWay argv.[0]
            printfn ""
    0
 1 
 2 
 3 
 4 
 5 
 6 
 7 
 8 Buttonsモジュールを使う
 9 Roboモジュールを使う
10 
11 BasicWheelオブジェクトを作る
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 


動作リスト(myway.txt)
straight 20
rotate 90
straight 30
rotate 90
straight 20
rotate 90
straight 30
rotate 90