How to execute a function just once in the void loop? - arduino

Simply, I want to make a counter to execute a subroutine if digital read gets a toggle value just thefirst time. But the result shows that the "aFunction" executes more than once (repeatedly).
Code:
int lastState = 1;
void setup() {
Serial.begin(115200);
}
void loop() {
int currentState = digitalRead(D5);
if (currentState == 1) {
if (currentState = !lastState) {
aFunction();
}
lastState = !lastState;
}
Serial.println("Still running loop");
delay(2000);
}
void aFunction() {
Serial.println("in a function");
}

This is the final result:
bool executed = false;
void setup()
{
Serial.begin(115200);
}
void loop()
{
int currentState = digitalRead(D5);
if (currentState == 1 && executed == false)
{
aFunction();
executed = true;
}
if (currentState == 0 && executed == true)
{
aFunction();
executed = false;
}
Serial.println("Still running loop");
delay(2000);
}
void aFunction()
{
Serial.println("in a function");
}

By keeping track of execution of function and checking it along with currentState variable will help you in achieving your goal.
Your code with this change will look like:
bool executed = false;
void setup() {
Serial.begin(115200);
}
void loop() {
int currentState = digitalRead(D5);
if (currentState == 1 && executed == false) {
executed = true;
aFunction();
}
Serial.println("Still running loop");
delay(2000);
}
void aFunction() {
Serial.println("in a function");
}

You need a variable to signal it's been run once:
int lastState = 1;
int runOnce = 0;
void setup() {
Serial.begin(115200);
}
void loop() {
int currentState = digitalRead(D5);
if (currentState == 1) {
if (currentState = !lastState) {
if (runOnce == 0)
aFunction();
}
lastState = !lastState;
}
Serial.println("Still running loop");
delay(2000);
}
void aFunction() {
Serial.println("in a function");
runOnce = 1;
}
So now your aFunction() sets the runOnce flag to 1 and it won't ever run again until the device is reset due to the if statement inside loop().

Your problem lies right here:
if (currentState == 1) {
if (currentState = !lastState) {
aFunction();
}
lastState = !lastState;
}
This will run indefinitely until currentState /= 1. You are having problems because you're not exactly understanding how the code runs in runtime. The computer is reading this repeatedly, and its reading if currentState==1 to execute the bracket.
The next issue is your nested if statement, it's not using a comparison operator. You have an = sign, but you should have an == operator to compare currentstate to laststate.
Essentially, if you want it to run once, you need to make sure the function changes the variable currentState to something other than 1, then if you want this function to execute again at some other point during runtime, change currentState back 1 for this function to run again, where again it'll change currentState to something other than 1.
I suggest instead of using an integer for currentState to use a boolean true or false. If true, execute, change to false at the end - since its changed to false it wont run again until its true again.

Related

Keyboard Emulator Typing Without Input

I made a keyboard emulator with my Arduino and hooked it up to some switches, thought I'd test them out in OSU. Osu, while it can be played with one key is best with two so naturally, I tried to add another switch/key to my emulator. This broke my emulator completely and caused it to start spitting out characters without any input. I've rewritten this script twice so forgive me if it's kind of frantic but can anyone tell me what's causing this?
Code:
#include <Keyboard.h>
void setup() {
// put your setup code here, to run once:
pinMode (2, INPUT_PULLUP);
pinMode (5, INPUT_PULLUP);
Serial.begin(9600);
}
void loop() {
// put your main code here, to run repeatedly:
bool keyL = false;
bool keyR = false;
Keyboard.begin();
if (digitalRead (2) == 0){ //if switch 2 is activated
keyL = true;
}
else{
}//do nothing
if (digitalRead (5) == 0){
keyR = true;
}
else{
}//do nothing
if (keyR = true){
Keyboard.press ('c');
delay (50);
if (digitalRead (5) == 1){
keyR = false;
Keyboard.releaseAll();
}
}
if (keyL = true){
Keyboard.press ('z');
delay (50);
if (digitalRead (2) == 0){
keyL = false;
Keyboard.releaseAll();
}
}
}
It happens because the = operator is used for assignment only, and it returns the value of the assignment. so the expressions (keyR = true) inside if (keyR = true){ and (keyL = true) inside if(keyL = true){ always return true.
To compare the value of 2 variables you have to use the == operator:
#include <Keyboard.h>
void setup() {
// put your setup code here, to run once:
pinMode (2, INPUT_PULLUP);
pinMode (5, INPUT_PULLUP);
Serial.begin(9600);
}
void loop() {
// put your main code here, to run repeatedly:
bool keyL = false;
bool keyR = false;
Keyboard.begin();
if (digitalRead (2) == 0){ //if switch 2 is activated
keyL = true;
}
else{
}//do nothing
if (digitalRead (5) == 0){
keyR = true;
}
else{
}//do nothing
if (keyR == true){
Keyboard.press ('c');
delay (50);
if (digitalRead (5) == 1){
keyR = false;
Keyboard.releaseAll();
}
}
if (keyL == true){
Keyboard.press ('z');
delay (50);
if (digitalRead (2) == 0){
keyL = false;
Keyboard.releaseAll();
}
}
}

How can I exit a 'for' loop in the main Arduino loop with a serial command?

I need to exit a 'for' loop running in the main loop on an Arduino board through a serial command, but it looks like that up to the end of the main loop the Serial Event is not taken in consideration. How can I solve this?
I supply some simplified code to have a better understanding of the problem:
boolean start = false;
boolean abortLoop = false;
String inputString = "";
void setup() {
Serial.begin(9600);
}
void loop() {
if(start) {
Serial.println("start");
for(int i=0; i <10; i++) {
if(abortLoop)
break;
Serial.println(i);
delay(1000);
}
start = false;
abortLoop = false;
}
}
void serialEvent()
{
while (Serial.available())
{
// Get the new byte:
char inChar = (char)Serial.read();
// Add it to the inputString:
inputString += inChar;
//Serial.println(inputString);
// If the incoming character is a newline, set a flag
// so the main loop can do something about it:
if (inChar == '\n')
{
inputString = inputString.substring(0, inputString.length() - 1);
//Serial.println(inputString);
//Serial.println(inputString.length());
if (inputString[0] == 's')
{
Serial.println("start");
start = true;
}
if (inputString[0] == 'a')
{
abortLoop = true;
Serial.println("abort");
}
inputString = "";
}
}
}
If sending the command 'a' in the middle of the loop, the loop keeps going up to the end.
The result is:
start
start
0
1
2
3
4
5
6
7
8
9
abort
abort
In this case, the 'a' command was sent two times.
The solution is pretty simple. The only thing you have to do is to call your function in the for loop, else the function can't be executed.
// ...
for(int i=0; i <10; i++) {
serialEvent();
if(abortLoop)
break;
Serial.println(i);
delay(1000);
}
// ...
Moreover, I think it's better if you call your function at this place too:
// ...
void loop() {
serialEvent();
if(start) {
// ...
It's strangely not necessary, but in my opinion it's better. And 'start' is printed out two times, because you call it two times. One time here:
void loop() {
if(start) {
Serial.println("start");
for(int i=0; i <10; i++) {
and another time here:
if (inputString[0] == 'a')
{
abortLoop = true;
Serial.println("abort");
}
so you can remove one of them.

Start and Stop Stepper Motor using Serial Interface

Here's my code for starting a Stepper motor and trying to stop the motor:
#include <BasicStepperDriver.h>
#define DIR 34
#define STEP 36
#define ENBL 30
BasicStepperDriver stepper1(10000, DIR, STEP, ENBL);
BasicStepperDriver stepper2(10000, DIR, STEP, ENBL);
bool enableMotor1 = false;
bool enableMotor2 = false;
void rotate1() {
Serial.println("Rotate start 1");
stepper1.rotate(360);
Serial.println("Rotate end 1");
}
void rotate2() {
Serial.println("Rotate start 2");
stepper2.rotate(360);
Serial.println("Rotate end 2");
}
void setup() {
// put your setup code here, to run once:
Serial.begin(9600);
stepper1.enable();
stepper1.setMicrostep(1);
stepper1.setRPM(50);
stepper2.enable();
stepper2.setMicrostep(1);
stepper2.setRPM(50);
}
void loop() {
if(enableMotor1 == true) {
rotate1();
} else if(enableMotor2 == true) {
rotate2();
}
if (Serial.available ()) {
String first = Serial.readStringUntil(',');
Serial.read();
String second = Serial.readStringUntil(',');
if(first == "start"){
if(second == "1") {
Serial.println("Starting motor 1");
enableMotor1 = true;
}
if(second == "2") {
Serial.println("Starting motor 2");
enableMotor2 = true;
}
} else if(first == "stop") {
if(second == "1") {
Serial.println("Stopping motor 1");
enableMotor1 = false;
stepper1.disable();
}
if(second == "2") {
enableMotor2 = false;
Serial.println("Stopping motor 1");
stepper2.disable();
}
}
}
}
The problem with this code is that it is not possible to stop the motor through Serial interface. The goal is to have the Stepper motor running until the stop command is entered in the serial monitor. What could be wrong in my code?
This image shows that we can start the motor but can't be stopped:

How to translate code from Arduino to Raspberry Pi?

I have an Arduino Uno program and want to translate it code a Raspberry Pi 2. I am building a robotic kitchen pantry, and coded an LED state machine in order to represent it. The physical machine I plan to control has two main functions.
Functions
(1) The elevator moves to one of these three levels:
- 0 : Reset / Home
- 1 : Shelve 1
- 2 : Shelve 2
(2) The shelves move in/out of the elevator.
- Mount
- Unmount
I am currently using LEDs to represent motors / sensors in order to unit test my code. I understand that in order to make my code more robust I will require better handling of timing, something that the Raspberry Pi can afford to do.
Here is my current code:
// 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);
}
}
Just to clarify, you can still use C++ to develop apps for Win10 IoT.
I built for you a similar one in 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);
}
}
}
}
There are a few items to realize here
IoT Applications have the concept of a background application. See documentation here: http://ms-iot.github.io/content/en-US/win10/BackgroundApplications.htm
Note: It says background App, which may be confusing as it does not run like a background app in typical UWP does. The bootloader for IoT removes performance and cpu priority bottlenecks typically imposed on Background Applications for UWP and therefor runs just like a Foreground Application, just it is headless and a bit of an easier headless starting point. It also more closely resembles your Arduino code.
You should use enums for managing your state so it is centralized and easier to deal with.
In windows 10 IoT, you have the ability to setup event handlers for when events happen and process them instead of necessarily looping and watching. This will help in that events will be queued up and then processed. It may not be quite as speedy in some scenarios however, but in this instance it should be fine. If you need to loop, you may want to spin off a task that loops and watches
Finally in an event based multi-threaded system, you will need to guard processing state changes simultaneously from different threads by locking an object.
I have provided sample code based on your code base addressing all of the above. Note it is not completed, but should serve as a good starting point.
First you will need to create a background application and add a reference to the IoT extensions.
Here is the code:
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.
}
}
}
There are two ways:
Way 1 - You can directly use Arduino code onto your Windows IoT with minor changes.
Way 2 - By converting Arduino code into equivalent C# UWP.
Way 1: Use Arduino code directly on your Windows IoT
Setup Arduino Wiring for Windows IoT (refer this link)
Port your Arduino code (written above) onto your Windows IoT with pinmap of 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).
Way 2: Converting Arduino code to C# UWP
Converting Arduino code into C# UWP is not much complicated. You just have to convert Arduino functions into its equivalent C# UWP Windows IoT functions:

Arduino making decision according to a packet received from serial port

The program listen to messages from serial port in the form or where first character (A or D) means analog or digital, the 2nd character - pin, the 3rd character - 1/0 or from 0 to 255. The markers < and > show the beginning and the end of packet.
For example, if packet is received, the light is turned on by digitalWrite(13,1)
But nothing happens. When I send via serial monitor, for instance: light is supposed to blink but it does not. The same with analogue outputs.
bool started = false;
bool ended = false;
char inData[5];
byte index;
void setup()
{
Serial.begin(9600);
}
void loop()
{
while (Serial.available() > 0)
{
char inChar = Serial.read();
if (inChar == '<')
{
index = 0;
started = true;
ended = false;
}
else if (inChar == '>')
{
ended = true;
break;
}
else
{
if (index <= 4)
{
inData[index] = inChar;
index++;
}
}
if (started && ended)
{
if (inData[0] == 'A')
{
pinMode(inData[2],OUTPUT);
analogWrite(inData[2],inData[4]);
}
else if (inData[0] == 'D')
{
if (inData[4] == 1)
{
pinMode(inData[2],OUTPUT);
digitalWrite(inData[2],HIGH);
}
else if (inData[4] == 0)
{
pinMode(inData[2],OUTPUT);
digitalWrite(inData[2],LOW);
}
}
started = false;
ended = false;
index = 0;
}
}
Serial.println("Sending");
}
The following code will allow you to execute a method with an example serial string:
<power,led>
Once it processes this string, it'll execute the following method:
sendCommand(cmd, val);
See below for an example of how to turn on an LED on PIN 11.
#include <avr/pgmspace.h>
int IRledPin = 11;
#define SOP '<'
#define EOP '>'
bool started = false;
bool ended = false;
char inData[80];
byte index;
void setup() {
pinMode(IRledPin, OUTPUT);
Serial.begin(9600);
}
void loop() {
// Read all serial data available, as fast as possible
while (Serial.available() > 0) {
char inChar = Serial.read();
if (inChar == SOP) {
index = 0;
inData[index] = '\0';
started = true;
ended = false;
} else if (inChar == EOP) {
ended = true;
break;
} else {
if (index < 79) {
inData[index] = inChar;
index++;
inData[index] = '\0';
}
}
}
// We are here either because all pending serial
// data has been read OR because an end of
// packet marker arrived. Which is it?
if (started && ended) {
// The end of packet marker arrived. Process the packet
char *cmd = strtok(inData, ",");
if (cmd) {
char *val = strtok(NULL, ",");
if (val) {
sendCommand(cmd, val);
}
}
// Reset for the next packet
started = false;
ended = false;
index = 0;
inData[index] = '\0';
}
}
void sendCommand(char *command, char *value) {
if (strcmp(command,"power") == 0) {
power(value);
}
}
void power(char* value) {
if (strcmp(value, "led") == 0) {
digitalWrite(IRledPin, HIGH);
}
}
If the 2nd character is the pin, then you want inData[1] for your pin numbers instead of inData[2].
Why do you go from inData[0] to inData[2]? Wouldn't the second character be in inData[1]?
You're setting the pinMode to the actual value of inData[2]. That means to turn on pin 13, you need to send a carriage return character ('\r').
The code doesn't run below but it should help you to sort out your problem.
What it tries to do is split the inData into the Tokens[] array.
It then turns the ASCII data into integers with the atoi() statement.
Hope it helps.
Got the splitter from Segmentation Fault when using strtok_r
bool started = false;
bool ended = false;
char inData[5];
byte index;
void setup()
{
Serial.begin(9600);
}
void loop()
{
while (Serial.available() > 0)
{
char inChar = Serial.read();
if (inChar == '<')
{
index = 0;
started = true;
ended = false;
}
else if (inChar == '>')
{
ended = true;
break;
}
else
{
inData[index] = inChar;
index++;
}
if (started && ended)
{
// https://stackoverflow.com/questions/2227198/segmentation-fault-when-using-strtok-r
// Splint up input data
char *p = inData;
char *tokens[50];
int i = 0;
while (i < 50) {
tokens[i] = strtok_r(p, ",", &p);
if (tokens[i] == NULL) {
break;
}
i++;
}
if (tokens[0] == '<A')
{
pinMode(tokens[1],OUTPUT);
analogWrite(tokens[2],tokens[3]);
}
else if (token[0] == '<D')
{
if (atoi(token[3]) == 1)
{
pinMode(atoi(token[1]),OUTPUT);
digitalWrite(atoi(token[1]),HIGH);
}
else if (atoi(tokens[3]) == 0)
{
pinMode(atoi(tokens[1]),OUTPUT);
digitalWrite(atoi(tokens[1]),LOW);
}
}
started = false;
ended = false;
index = 0;
}
}

Resources