/**
* This code will run automatically on the photon.
* By calling the
*
* If we flash all of the photons/argons with this code before sending
* them to the students, the devices will be able to talk to matlab
* over serial.
*
* TODO
* - Test the code THOROUGHLY
*
* ref:
* System modes: https://docs.particle.io/reference/device-os/firmware/photon/#system-modes
* Serial ref: https://docs.particle.io/reference/device-os/firmware/photon/#serial
* Photon source: https://github.com/particle-iot/device-os/tree/develop/user/inc
* Arduino String ref: https://www.arduino.cc/reference/en/language/variables/data-types/stringobject/
*/
#include "Particle.h"
/**Dummy values so vscode works right.**/
#ifndef PARTICLE_H
extern Particle;
extern Serial;
typedef struct Servo_V Servo;
typedef struct String_V String;
enum pins {
A0, A1, A2, A3, A4, A5, A6, A7,
D0, D1, D2, D3, D4, D5, D6, D7,
INPUT, OUTPUT
}
#endif /* PARTICLE_H */
/**End: Dummy values**/
/**Varaibles needed for online accesss**/
Servo myservo; // Create servo object to control a servo
int pos = 70; // Store the position of the servo
double pulse = -1; //length of pulse
int pulsePin = -1; //pulse pin
int servoPin = -1; //servo pin
int freq =2000; // Set the frequency of the analogWrite()
int reading[18] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; // Store the memory of the read data or the written
int memory[18] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; // Store the memory of the read data or the written
int t = 200; //Set milliseconds of averaging
int readVar[18] = {-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1}; //Stores whether the pin is reading (1), writing (0), or uninitialized(-1) or Servo (2)
String strTemp =""; //memory as string
String strTemp2 =""; // read as string
/**End: Varaibles needed for online accesss**/
SYSTEM_MODE(MANUAL); // runs w/o connecting to cloud
//SYSTEM_MODE(SEMI_AUTOMATIC);
// enum of integers that correspond to a command
enum comms {
f_CONNECT = 1,
f_GETPINMODE = 2,
f_ISCONNECTED = 3,
f_SETINPUT = 4,
f_SETOUTPUT = 5,
f_ANALOGREAD = 6,
f_DIGITALREAD = 7,
f_ANALOGWRITE = 8,
f_DIGITALWRITE = 9,
f_GETPIN = 10,
f_DISCONNECT = 11
};
// 1 if the photon has connected with the cloud before, 0 if not.
int firstConnect = 0;
void setup() {
// try to setup serial connection
Serial.begin();
delay(100);
/*if (!Serial.isConnected()) {
// assume you want to connect over IP
expose();
}*/
// connect to internet; if you don't want it to do so
// right off the bat, comment out this block
{
Particle.connect();
}
// expose functions
expose();
pinMode(A0, OUTPUT);
analogWrite(A0, 0);
pinMode(A1, OUTPUT);
analogWrite(A1, 0);
pinMode(A2, OUTPUT);
analogWrite(A2, 0);
pinMode(A3, OUTPUT);
analogWrite(A3, 0);
pinMode(A4, OUTPUT);
analogWrite(A4, 0);
pinMode(A5, OUTPUT);
analogWrite(A5, 0);
pinMode(D0, OUTPUT);
digitalWrite(D0,0);
pinMode(D1, OUTPUT);
digitalWrite(D1,0);
pinMode(D2, OUTPUT);
digitalWrite(D2,0);
pinMode(D3, OUTPUT);
digitalWrite(D3,0);
pinMode(D4, OUTPUT);
digitalWrite(D4,0);
pinMode(D5, OUTPUT);
digitalWrite(D5,0);
pinMode(D6, OUTPUT);
digitalWrite(D6,0);
pinMode(D7, OUTPUT);
digitalWrite(D7,0);
}
void loop() {
// first, check the serial connection
if (Serial.available()) {
// get first byte from the USB
int comm = Serial.read();
String arg = "";
// find the command that was called
switch (comm) {
case f_DISCONNECT:
Particle.disconnect();
WiFi.off();
{
int i = 1;
Serial.write(i);
}
break;
case f_CONNECT:
Particle.connect();
// not sure if need to, but expose again
expose();
case f_ISCONNECTED:
if (Particle.connected()) {
int i = 1;
Serial.write(i);
} else {
int i = 0;
Serial.write(i);
}
break;
case f_GETPINMODE:
getStr(arg, 3);
Serial.write(pMode(arg));
break;
case f_SETINPUT:
getStr(arg, 3);
Serial.write(setInput(arg));
break;
case f_SETOUTPUT:
getStr(arg, 3);
Serial.write(setOutput(arg));
break;
case f_ANALOGREAD:
getStr(arg, 3);
{
int res = aread(arg);
int mask = 0b0000000011111111;
Serial.write(res & mask);
Serial.write(res >> 8);
}
break;
case f_DIGITALREAD:
getStr(arg, 3);
Serial.write(dread(arg));
break;
case f_ANALOGWRITE:
getStr(arg, -1);
{
int res = awrite(arg);
int mask = 0b0000000011111111;
Serial.write(res >> 8);
Serial.write(res & mask);
}
break;
case f_DIGITALWRITE:
getStr(arg, -1);
Serial.write(dwrite(arg));
break;
case f_GETPIN:
getStr(arg, 3);
Serial.write(getPin(arg));
break;
default:
Serial.write(-1);
break;
}
}
// next, check the
if (Particle.connected()) {
Particle.process();
}
/**The rest of this function is required whether offline or not;
* it stores the data from the pins in memory so they can be returned
* in the function calls
*/
//Read through the analog pins
for(int m =0;m<t;m++)
{
for(int n = 10;n<=17;n++)
{
// If the pin is a writing pin
if(readVar[n] == 0)
{
//Write the value
analogWrite(n,memory[n]);//, freq);
}
// If the pin is a reading pin
else if (readVar[n] == 1)
{
//Iterate t times with a 1 ms delay to average out the analog reads
reading[n] += analogRead(n);
delay(1);
//Store the average value into memory
}
}
}
for(int n = 10;n<=17;n++)
{
if (readVar[n] == 1)
{
memory[n] = int(reading[n]/t);
reading[n] = 0;
}
}
//Read through the digital pins
for(int n = 0;n<=7;n++)
{
//If a writing pin
if(readVar[n] == 0)
{
//Write the value to the pin
digitalWrite(n,memory[n]);
}
//If a reading pin
else if (readVar[n] == 1)
{
//Read the value of the pin
memory[n]=digitalRead(n);
}
}
// Initialize null strings
strTemp = "";
strTemp2 = "";
//Concatenate array values into the string
for(int n = 0;n<17;n+=1)
{
strTemp.concat(String(memory[n]));
strTemp.concat(',');
strTemp2.concat(String(readVar[n]));
strTemp2.concat(',');
}
strTemp.concat(String(memory[17]));
strTemp2.concat(String(readVar[17]));
/**End: required stuff section**/
}
/*
Function that exposes all other functions to the cloud.
*/
void expose() {
Particle.function("move",slide); //Particle function to relate slide to move
Particle.function("attachServo",attachServo); //Particle function to attachServo
Particle.function("detachServo",detachServo); //Particle function to detachServo
Particle.function("setInput",setInput); //Particle function to set the pinMode to input
Particle.function("setOutput",setOutput); //Particle function to set the pinMode to output
Particle.function("pinMode",pMode); //Particle function to get the pinMode where Input is 1 and Output is 0
Particle.function("getPin",getPin); //Particle function to translate string of pin to integer number
Particle.function("analogWrite",awrite); //Particle function to write value to analog pin
Particle.function("analogRead",aread); //Particle function to read analog pin
Particle.function("digitalWrite",dwrite); //Particle function to write value to digital pin
Particle.function("digitalRead",dread); //Particle function to read value from digital pin
Particle.function("setFreq",setf); //Particle function to set the analog write frequency
Particle.function("getPulse",getPulse); //Particle function to get the input frequency on an analog pin
Particle.function("setAvgTime",setAvgTime); //Particle function to get the input frequency on an analog pin
Particle.variable("position",pos); //Particle variable to get the position of the servo
Particle.variable("frequency",freq); //Particle variable to get the frequency of the analog write
Particle.variable("String",strTemp); //Particle variable to get the memory string
Particle.variable("String2",strTemp2); //Particle variable to get the read string
Particle.variable("String2",strTemp2); //Particle variable to get the read string
Particle.variable("pulse",pulse); //Particle variable to get the frequency of the analog write
}
/*
Tries to grab len bytes from Serial and puts the bytes in str as
chars. str must be an arduino String object. This function either
reads len bytes or reads the number of bytes available if there
are less than len bytes left.
Returns the number of bytes read (including any null bytes).
NOTE: if len == -1, the string can be infinite.
*/
int getStr(String& str, int len) {
int amt = 0;
char lastChar = 'a';
int avail = Serial.available();
while (amt < avail && amt != len) {
lastChar = (char)Serial.read(); // assumes data only in 1 byte even int is 32 bit
amt++;
str += lastChar;
}
return amt;
}
/********************IP ONLY FUNCTIONS**********************
***********************************************************
***********************************************************
***********************************************************
***********************************************************/
int slide(String angle) //spark function slide will take the string it receives (turn) and output it as "angle"
{
myservo.write(angle.toInt()); //convert angle to an integer and
pos = angle.toInt(); //set position as the angle
delay(10);
return pos; //necessary for the servo
}
int getPin(String pin) //Translate the string of the pin to an integer
{
if(pin.equals("A1")){
return A1;
}
else if(pin.equals("A2")){
return A2;
}
else if(pin.equals("A3")){
return A3;
}
else if(pin.equals("A4")){
return A4;
}
else if(pin.equals("A5")){
return A5;
}
else if(pin.equals("A6")){
return A6;
}
else if(pin.equals("A7")){
return A7;
}
else if(pin.equals("A0")){
return A0;
}
else if(pin.equals("D0")){
return D0;
}
else if(pin.equals("D1")){
return D1;
}
else if(pin.equals("D2")){
return D2;
}
else if(pin.equals("D3")){
return D3;
}
else if(pin.equals("D4")){
return D4;
}
else if(pin.equals("D5")){
return D5;
}
else if(pin.equals("D6")){
return D6;
}
else if(pin.equals("D7")){
return D7;
}
else{
return -1;
}
}
int attachServo(String pin) //Attach a servo to a pin
{
int p = getPin(pin); //convert pin to an integer
if(p>-1 && readVar[p]==-1)
{
myservo.attach(p);
servoPin = p;
delay(10);
readVar[p] = 2;
return p;
}
return -1;
}
int detachServo(String pin) //Detach a servo to a pin
{
myservo.detach(); //convert pin to an integer
readVar[servoPin] = -1;
servoPin = -1;
delay(10);
return 1;
}
int setInput(String pin) //Set the pin to an input pin
{
int p = getPin(pin);
if(p>-1 && readVar[p]==-1)
{
pinMode(p, INPUT);
readVar[p] = 1;
return 1;
}
return -1;
}
int setOutput(String pin) //Set the pin to an output pin
{
int p = getPin(pin);
if(p>-1 && readVar[p]==-1)
{
pinMode(p, OUTPUT);
readVar[p] = 0;
return 1;
}
return -1;
}
int pMode(String pin) //Get whether a pin is input(1) or output(0)
{
int p = getPin(pin);
if (getPinMode(p)==INPUT)
{
return 1;
}
return 0;
}
int awrite(String pin) //Takes an input argument with syntax "pin,value" ex. "A0,255"
{
int t = pin.indexOf(",");
int p = getPin(pin.substring(0,t));
//int t2 = pin.indexOf(",",t);
int t3 = pin.lastIndexOf(",");
String p1 = pin.substring(t3+1);
int val = p1.toInt();
//pinMode(p,OUTPUT);
readVar[p] = 0;
memory[p] = val;
return val;
}
int aread(String pin) //Read analog value from a pin
{
int p = getPin(pin);
return memory[p];
}
int dwrite(String pin) //write a value to a digital pin
{
int t = pin.indexOf(",");
int p = getPin(pin.substring(0,t));
//int t2 = pin.indexOf(",",t);
int t3 = pin.lastIndexOf(",");
String p1 = pin.substring(t3+1);
int val = p1.toInt();
if(abs(val)==0){
memory[p] = 0;
return 0;
}
else{
memory[p] = 1;
return 1;
}
return val;
}
int dread(String pin) //Read a value from a digital pin
{
int p = getPin(pin);
return memory[p];
}
int setAvgTime(String val) //Read a value from a digital pin
{
int t = val.toInt();
return t;
}
int setf(String fre) //Set the frequency of the analog write
{
freq =fre.toInt();
return freq;
}
int getPulse(String pin) //get the tone of the analog read
{
pulsePin = getPin(pin);
setInput(pin);
pinMode(pulsePin,INPUT);
double duration = pulseIn(pulsePin, HIGH);
duration += pulseIn(pulsePin, LOW);
return 1.0/(duration/1000000.0);;
}
/**END: IP functions, Vars, and Values**/