如何将代码从 Arduino 翻译成 Raspberry Pi?

How to translate code from Arduino to Raspberry Pi?

我有一个 Arduino Uno 程序,想将其翻译成代码 Raspberry Pi 2. 我正在构建一个机器人厨房餐具室,并编写了一个 LED 状态机以表示它。我打算控制的物理机主要有两个功能。

函数

(1) 电梯移动到以下三层之一: - 0:重置/主页 - 1 : 搁置 1 - 2 : 搁置 2

(2) 电梯的货架移动in/out。 - 山 - 卸载

我目前正在使用 LED 来表示电机/传感器,以便对我的代码进行单元测试。我明白,为了让我的代码更健壮,我需要更好地处理时序,这是 Raspberry Pi 可以负担得起的事情。

这是我当前的代码:

    // Sensors for shelves. True if shelf is loaded.
boolean s1 = false;
boolean s2 = false; 

// Buttons to ask to shelves.
boolean input1 = false;
boolean input2 = false; 

// Elevator level (0, 1, or 2)
int elevator = 0;

// Elevator Level LEDs (Red)
int elevatorReset = 13;
int elevatorOne = 12;
int elevatorTwo = 11;

// Shelve State LEDs (Green) (On if loaded, Off if hidden)
int ShelveOne = 10; // Top Shelve
int ShelveTwo = 9; // Bottom Shelve


// Buttons
int ButtonOne = 2; // Request Shelve One
int ButtonTwo = 3; // Request Shelve Two
int ButtonReset = 4; // Request Reset

// Debouncing
unsigned long lastTime1 = 0;
unsigned long lastTime2 = 0;
const long interval = 300;


void setup() {
pinMode(elevatorReset, OUTPUT); // declare LED as output 
pinMode(elevatorOne, OUTPUT); // declare LED as output 
pinMode(elevatorTwo, OUTPUT); // declare LED as output

pinMode(ShelveOne, OUTPUT); // declare LED as output
pinMode(ShelveTwo, OUTPUT); // declare LED as output

pinMode(ButtonOne, INPUT); // make button 1 an input 
pinMode(ButtonTwo, INPUT); // make button 2 an input 
pinMode(ButtonReset, INPUT); // make button 3 an input 
}

void loop() {

unsigned long currentTime = millis();

level(0);

// Request Shelf 1
if (digitalRead(ButtonOne) == LOW) 
{
  pickup(1);
  deliver(1);
}

// Request Shelf 2
if (digitalRead(ButtonTwo) == LOW)
{
  pickup(2);
  deliver(2);  
}

// Request Reset
if (digitalRead(ButtonReset) == LOW) 
{
  reset();
}

}

void pickup(int num){
  if (num == 1)
  {
    level(0);
    delay(500);
    level(1);
    delay(500);
    load(1);
  }
  else if (num == 2)
  {
    level(0);
    delay(500);
    level(1);
    delay(500);
    level(2);
    delay(500);
    load(2);
  }
  else if (num == 0)
  {

  }
}

void dropoff(int num){
  if (num == 1)
  {
    level(1);
    delay(500);
    unload(1);
  }
  else if (num == 2)
  {
    level(1);
    delay(500);
    level(2);
    delay(500);
    unload(2);
  }
}



void deliver(int num)
{
  if (elevator == 1)
  {
    delay(1000);
    level(0);
    //blink();
  }

  if (elevator == 2)
  {
    delay(1000);
    level(1);
    delay(500);
    level(0);
    //blink();
  }
}

void level(int num)
{
  if (num == 0)
  {
    digitalWrite(elevatorReset, HIGH);
    digitalWrite(elevatorOne, LOW);
    digitalWrite(elevatorTwo, LOW);
    elevator = 0;
  }
  else if (num == 1)
  {
    digitalWrite(elevatorReset, LOW);
    digitalWrite(elevatorOne, HIGH);
    digitalWrite(elevatorTwo, LOW);
    elevator = 1;
  }
  else if (num == 2)
  {
    digitalWrite(elevatorReset, LOW);
    digitalWrite(elevatorOne, LOW);
    digitalWrite(elevatorTwo, HIGH);
    elevator = 2;
  }
}

void load(int num){
  if (num == 1)
  {
    digitalWrite(ShelveOne, HIGH);
    digitalWrite(ShelveTwo, LOW);
    s1 = true;
  }
  else if (num == 2)
  {
    digitalWrite(ShelveOne, LOW);
    digitalWrite(ShelveTwo, HIGH);
    s2 = true;
  }
}

void unload(int num){
  if (num == 1)
  {
    digitalWrite(ShelveOne, LOW);
    s1 = false;
  }
  else if (num == 2)
  {
    digitalWrite(ShelveTwo, LOW);
    s2 = false;
  }
}

void reset()
{
if (s1 == true)
        {
            delay(500);
            dropoff(1);
            delay(500);
            level(0);
        }

else if (s2 == true)
        {
            delay(500);
            dropoff(2);
            delay(500);
            level(1);
            delay(500);
            level(0);
        }
}

void blink ()
{
  delay(1000);
  while( !(digitalRead(ButtonOne) == LOW || digitalRead(ButtonTwo) == LOW || digitalRead(ButtonReset) == LOW) )
  {
  digitalWrite(elevatorReset, HIGH);  // wait for a second
  delay(200);
  digitalWrite(elevatorReset, LOW);  // wait for a second
  delay(200);
  }
}

澄清一下,您仍然可以使用 C++ 为 Win10 IoT 开发应用程序。

我用 C# 为你构建了一个类似的:

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Runtime.InteropServices.WindowsRuntime;
using System.Threading.Tasks;
using Windows.Devices.Gpio;
using Windows.Foundation;
using Windows.Foundation.Collections;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Controls.Primitives;
using Windows.UI.Xaml.Data;
using Windows.UI.Xaml.Input;
using Windows.UI.Xaml.Media;
using Windows.UI.Xaml.Navigation;

// The Blank Page item template is documented at http://go.microsoft.com/fwlink/?LinkId=402352&clcid=0x409

namespace App6
{
    /// <summary>
    /// An empty page that can be used on its own or navigated to within a Frame.
    /// </summary>
    public sealed partial class MainPage : Page
    {
        private static GpioPin GpioPin1;
        private static GpioPin GpioPin2;
        private static GpioPin GpioPin3;
        private static GpioPin GpioPin4;
        private static GpioPin GpioPin5;
        private static GpioPin GpioPin6;
        private static GpioPin GpioPin7;
        private static GpioPin GpioPin8;

    // Sensors for shelves. True if shelf is loaded.
    bool s1 = false;
    bool s2 = false;

    // Buttons to ask to shelves.
    bool input1 = false;
    bool input2 = false;

    // Elevator level (0, 1, or 2)
    int elevator = 0;

    // Elevator Level LEDs (Red)
    int elevatorReset = 13;
    int elevatorOne = 12;
    int elevatorTwo = 11;

    // Shelve State LEDs (Green) (On if loaded, Off if hidden)
    int ShelveOne = 10; // Top Shelve
    int ShelveTwo = 9; // Bottom Shelve


    // Buttons
    int ButtonOne = 2; // Request Shelve One
    int ButtonTwo = 3; // Request Shelve Two
    int ButtonReset = 4; // Request Reset

    // Debouncing
    long lastTime1 = 0;
    long lastTime2 = 0;
    const long interval = 300;
    private DispatcherTimer timer;

    public MainPage()
    {
        this.InitializeComponent();

        timer = new DispatcherTimer();
        timer.Interval = TimeSpan.FromMilliseconds(500);
        timer.Tick += Timer_Tick;

        InitGPIO();
    }

    private void InitGPIO()
    {
        var gpio = GpioController.GetDefault();

        // Show an error if there is no GPIO controller
        if (gpio == null)
        {
            GpioPin1 = null;
            GpioPin2 = null;
            GpioPin3 = null;
            GpioPin4 = null;
            GpioPin5 = null;
            GpioPin6 = null;
            GpioPin7 = null;
            GpioPin8 = null;

            return;
        }
        //pinMode(elevatorReset, OUTPUT); // declare LED as output 
        //pinMode(elevatorOne, OUTPUT); // declare LED as output 
        //pinMode(elevatorTwo, OUTPUT); // declare LED as output

        //pinMode(ShelveOne, OUTPUT); // declare LED as output
        //pinMode(ShelveTwo, OUTPUT); // declare LED as output

        //pinMode(ButtonOne, INPUT); // make button 1 an input 
        //pinMode(ButtonTwo, INPUT); // make button 2 an input 
        //pinMode(ButtonReset, INPUT); // make button 3 an input 
        GpioPin1 = gpio.OpenPin(elevatorReset);
        GpioPin2 = gpio.OpenPin(elevatorOne);
        GpioPin3 = gpio.OpenPin(elevatorTwo);
        GpioPin4 = gpio.OpenPin(ShelveOne);
        GpioPin5 = gpio.OpenPin(ShelveTwo);
        GpioPin6 = gpio.OpenPin(ButtonOne);
        GpioPin7 = gpio.OpenPin(ButtonTwo);
        GpioPin8 = gpio.OpenPin(ButtonReset);

        GpioPin1.Write(GpioPinValue.Low);
        GpioPin2.Write(GpioPinValue.Low);
        GpioPin3.Write(GpioPinValue.Low);
        GpioPin4.Write(GpioPinValue.Low);
        GpioPin5.Write(GpioPinValue.Low);

        GpioPin1.SetDriveMode(GpioPinDriveMode.Output);
        GpioPin2.SetDriveMode(GpioPinDriveMode.Output);
        GpioPin3.SetDriveMode(GpioPinDriveMode.Output);
        GpioPin4.SetDriveMode(GpioPinDriveMode.Output);
        GpioPin5.SetDriveMode(GpioPinDriveMode.Output);

        // Check if input pull-up resistors are supported
        if (GpioPin6.IsDriveModeSupported(GpioPinDriveMode.InputPullUp))
            GpioPin6.SetDriveMode(GpioPinDriveMode.InputPullUp);
        else
            GpioPin6.SetDriveMode(GpioPinDriveMode.Input);

        if (GpioPin7.IsDriveModeSupported(GpioPinDriveMode.InputPullUp))
            GpioPin7.SetDriveMode(GpioPinDriveMode.InputPullUp);
        else
            GpioPin7.SetDriveMode(GpioPinDriveMode.Input);

        if (GpioPin8.IsDriveModeSupported(GpioPinDriveMode.InputPullUp))
            GpioPin8.SetDriveMode(GpioPinDriveMode.InputPullUp);
        else
            GpioPin8.SetDriveMode(GpioPinDriveMode.Input);

    }

    private void Timer_Tick(object sender, object e)
    {

        //unsigned long currentTime = millis();

        level(0);

        // Request Shelf 1
        if (GpioPin6.Read() == GpioPinValue.Low)
        {
            pickup(1);
            deliver(1);
        }

        // Request Shelf 2
        if (GpioPin7.Read() == GpioPinValue.Low)
        {
            pickup(2);
            deliver(2);
        }

        // Request Reset
        if (GpioPin8.Read() == GpioPinValue.Low)
        {
            reset();
        }
    }


    async void pickup(int num)
    {
        if (num == 1)
        {
            level(0);
            await Task.Delay(500);
            level(1);
            await Task.Delay(500);
            load(1);
        }
        else if (num == 2)
        {
            level(0);
            await Task.Delay(500);
            level(1);
            await Task.Delay(500);
            level(2);
            await Task.Delay(500);
            load(2);
        }
        else if (num == 0)
        {

        }
    }

    async void dropoff(int num)
    {
        if (num == 1)
        {
            level(1);
            await Task.Delay(500);
            unload(1);
        }
        else if (num == 2)
        {
            level(1);
            await Task.Delay(500);
            level(2);
            await Task.Delay(500);
            unload(2);
        }
    }

    async void deliver(int num)
    {
        if (elevator == 1)
        {
            await Task.Delay(1000);
            level(0);
            //blink();
        }

        if (elevator == 2)
        {
            await Task.Delay(1000);
            level(1);
            await Task.Delay(500);
            level(0);
            //blink();
        }
    }

    void level(int num)
    {
        if (num == 0)
        {
            GpioPin1.Write(GpioPinValue.High);
            GpioPin2.Write(GpioPinValue.Low);
            GpioPin3.Write(GpioPinValue.Low);
            elevator = 0;
        }
        else if (num == 1)
        {
            GpioPin1.Write(GpioPinValue.Low);
            GpioPin2.Write(GpioPinValue.High);
            GpioPin3.Write(GpioPinValue.Low);
            elevator = 1;
        }
        else if (num == 2)
        {
            GpioPin1.Write(GpioPinValue.Low);
            GpioPin2.Write(GpioPinValue.Low);
            GpioPin3.Write(GpioPinValue.High);
            elevator = 2;
        }
    }

    void load(int num)
    {
        if (num == 1)
        {
            GpioPin4.Write(GpioPinValue.High);
            GpioPin5.Write(GpioPinValue.Low);
            s1 = true;
        }
        else if (num == 2)
        {
            GpioPin4.Write(GpioPinValue.Low);
            GpioPin5.Write(GpioPinValue.High);
            s2 = true;
        }
    }

    void unload(int num)
    {
        if (num == 1)
        {
            GpioPin4.Write(GpioPinValue.Low);
            s1 = false;
        }
        else if (num == 2)
        {
            GpioPin5.Write(GpioPinValue.Low);
            s2 = false;
        }
    }

    async void reset()
    {
        if (s1 == true)
        {
            await Task.Delay(500);
            dropoff(1);
            await Task.Delay(500);
            level(0);
        }

        else if (s2 == true)
        {
            await Task.Delay(500);
            dropoff(2);
            await Task.Delay(500);
            level(1);
            await Task.Delay(500);
            level(0);
        }
    }

    async void blink()
    {
        await Task.Delay(1000);
        while (!(GpioPin6.Read() == GpioPinValue.Low || GpioPin7.Read() == GpioPinValue.Low || GpioPin8.Read() == GpioPinValue.Low))
        {
            GpioPin1.Write(GpioPinValue.High);  // wait for a second
            await Task.Delay(200);
            GpioPin1.Write(GpioPinValue.Low);  // wait for a second
            await Task.Delay(200);
        }
    }

}

}

这里有几项需要实现

  1. 物联网应用程序有后台应用程序的概念。请参阅此处的文档:http://ms-iot.github.io/content/en-US/win10/BackgroundApplications.htm 注意:它说的是后台应用程序,这可能会造成混淆,因为它不像典型 UWP 中的后台应用程序那样 运行。 IoT 的引导加载程序消除了通常强加给 UWP 后台应用程序的性能和 cpu 优先级瓶颈,因此 运行s 就像前台应用程序一样,只是它是无头的,并且是一个更容易的无头起点。它也更类似于您的 Arduino 代码。
  2. 你应该使用枚举来管理你的状态,这样它是集中的并且更容易处理。
  3. 在 windows10 IoT 中,您可以为事件发生时设置事件处理程序并处理它们,而不必循环和观察。这将有助于将事件排队然后进行处理。然而,在某些情况下它可能不会那么快,但在这种情况下应该没问题。如果你需要循环,你可能想分拆一个循环和监视的任务
  4. 最后,在基于事件的多线程系统中,您需要通过锁定一个对象来保护来自不同线程的同时处理状态更改。

我已经根据您的代码库提供了解决上述所有问题的示例代码。请注意,它尚未完成,但应该作为一个很好的起点。

首先,您需要创建后台应用程序并添加对 IoT 扩展的引用。

代码如下:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Net.Http;
using Windows.ApplicationModel.Background;
using Windows.Devices.Gpio;
using System.Threading.Tasks;

// The Background Application template is documented at       http://go.microsoft.com/fwlink/?LinkID=533884&clcid=0x409
// Sensors for shelves. True if shelf is loaded.

namespace BackgroundApplication1
{
public sealed class StartupTask : IBackgroundTask
{
    public enum MachineState
    {
        unknown,
        initial,
        elevatorLevelOne,
        elevatorLevelTwo,
        transitionOnetoTwo,
        transitionTwotoOne,
        transitionOnetoReset,
        transitionTwotoReset
    }
    private MachineState currentState;
    private object lObj;
    // Elevator Level LEDs (Red)
    private const int elevatorResetPin = 13;
    private const int elevatorOnePin = 12;
    private const int elevatorTwoPin = 11;
    //Gpio for each
    GpioPin elevOneLed;
    GpioPin resetLed;
    GpioPin elevTwoLed;

    // Shelve State LEDs (Green) (On if loaded, Off if hidden)
    private const int ShelveOnePin = 10; // Top Shelve
    private const int ShelveTwoPin = 9; // Bottom Shelve
    GpioPin shelfOneLed;
    GpioPin shelfTwoLed;


    // Buttons
    private const int ButtonOne = 2; // Request Shelve One
    private const int ButtonTwo = 3; // Request Shelve Two
    private const int ButtonReset = 4; // Request Reset

    // Debouncing
    long lastTime1 = 0;
    long lastTime2 = 0;
    const long interval = 300;
    public void Run(IBackgroundTaskInstance taskInstance)
    {
        this.Initialize();
        Task.Run(() =>
        {
            while (true)
            {
                //thats right...do nothing.
            }
        });
    }

    public void Initialize()
    {
        GpioController gCon = GpioController.GetDefault();
        //Elevator LEDs
        elevOneLed = gCon.OpenPin(elevatorResetPin);
        resetLed = gCon.OpenPin(elevatorOnePin);
        elevTwoLed = gCon.OpenPin(elevatorTwoPin);
        elevOneLed.SetDriveMode(GpioPinDriveMode.Output);
        elevTwoLed.SetDriveMode(GpioPinDriveMode.Output);
        resetLed.SetDriveMode(GpioPinDriveMode.Output);
        //Shelf LEDs
        shelfOneLed = gCon.OpenPin(ShelveOnePin);
        shelfTwoLed = gCon.OpenPin(ShelveTwoPin);
        shelfOneLed.SetDriveMode(GpioPinDriveMode.Output);
        shelfTwoLed.SetDriveMode(GpioPinDriveMode.Output);

        //Buttons
        GpioPin buttonOne = gCon.OpenPin(ButtonOne);
        GpioPin buttonTwo = gCon.OpenPin(ButtonTwo);
        GpioPin buttonReset = gCon.OpenPin(ButtonReset);
        buttonOne.SetDriveMode(GpioPinDriveMode.Input);
        buttonTwo.SetDriveMode(GpioPinDriveMode.Input);
        buttonReset.SetDriveMode(GpioPinDriveMode.Input);
        buttonOne.ValueChanged += ButtonOne_ValueChanged;
        buttonTwo.ValueChanged += ButtonTwo_ValueChanged;
        buttonReset.ValueChanged += ButtonReset_ValueChanged;

        this.GetShelfOne();
    }

    private void GetShelfOne()
    {

            switch(this.currentState)
            {
                case MachineState.unknown: this.Reset();
                    break;
                case MachineState.elevatorLevelOne: 
                    break;
                case MachineState.elevatorLevelTwo: this.TransitionToShelfTwoFromOne();
                    break;
                case MachineState.transitionOnetoReset: //handle the rest of your stuff similiarly...
                    break;
            }

    }

    private void TransitionToShelfTwoFromOne()
    {
        this.shelfOneLed.Write(GpioPinValue.Low);
        this.shelfTwoLed.Write(GpioPinValue.High);            
        this.currentState = MachineState.elevatorLevelTwo;
    }

    private void Reset()
    {
        throw new NotImplementedException();
    }

    private void ButtonReset_ValueChanged(GpioPin sender, GpioPinValueChangedEventArgs args)
    {
        throw new NotImplementedException();
    }

    private void ButtonTwo_ValueChanged(GpioPin sender, GpioPinValueChangedEventArgs args)
    {
        throw new NotImplementedException();
    }

    private void ButtonOne_ValueChanged(GpioPin sender, GpioPinValueChangedEventArgs args)
    {
        //rising edge means you pushed the button
        if(args.Edge == GpioPinEdge.RisingEdge)
        {
            lock(lObj)
            {
                this.GetShelfOne();
            }
        }
        //falling edge means you released the button.
        //you could start a timer to see how long you held the button.
    }
}
}

有两种方法:

  1. 方式 1 - 您可以直接在您的 Windows IoT 上使用 Arduino 代码,稍作改动。
  2. 方式 2 - 通过将 Arduino 代码转换为等效的 C# UWP。

方式 1:直接在您的 Windows IoT

上使用 Arduino 代码
  1. 为 Windows IoT (refer this link)
  2. 设置 Arduino 布线
  3. 将您的 Arduino 代码(上面写的)移植到您的 Windows IoT 上,引脚图为 Raspberry Pi 2。

    Important Note: There are some rules to port Arduino written code to Windows IoT which is described at ms-iot website. The Arduino code you have provided can directly be ported on to Raspberry Pi 2 (make sure to change Arduino pin numbers to RPi2 pinmap).


方式 2:将 Arduino 代码转换为 C# UWP
将 Arduino 代码转换为 C# UWP 并不复杂。您只需将 Arduino 函数转换为等效的 C# UWP Windows IoT 函数: