i2c 2 Pi - Arduino i2c Slave
(Go back to i2c article)
// new i2c to Pi transceiver
//
// 8/2/16:0837 - version 0.51
// 8/3/16:0832 - version 0.6
//
#include <Wire.h>
#include <Servo.h>
#include <string.h>
#define SLAVE_ADDR 0x08
#define END_OF_STR '\x00'
#define SIG_BASE 0xA0
#define MAXSTR 20
#define CMD 1
#define CEND 2
#define CGET 4
#define CDATA 5
#define CDEND 6
#define WSLCT 7
#define WDATA 8
#define WDEND 9
#define DEBUG 1
const int flashpin = 13;
char recvStr[MAXSTR + 1];
char cdat[MAXSTR + 1];
int ccnt = 0;
unsigned char cmode = CMD;
//
// pin/function maps
// make sure pins are excluded from operations that are NOT good
// there MUST be a -1 at the end of each list unless ALL possible pins are included
//
// note: can really only control three analog devices at once!
// if pins 5 and 6 are used for PWM, the delay() and millis() functions won't work right.
// ...so pins 5,6 must be same freq; 9,10 same; 3,11 same
//
//Timer output Arduino Uno pins
//OC0A 6
//OC0B 5
//OC1A 9
//OC1B 10
//OC2A 11
//OC2B 3
//
const unsigned char alimit = 6, dlimit = 14;
unsigned char algList[6] = {0, 1, 2, 3, -1}; // can be pins 0-3 (avoid SCL/SDA)
unsigned char digiList[14] = {2, 4, 7, 8, 10, 12, -1};// can be pins 2-13 (avoid serial ports)
unsigned char digoList[14] = {13, -1}; // can be pins 2-13 (avoid serial ports)
unsigned char mtrList[6] = {6, -1}; // can be any of 3,5,6,9,10,11 but see above
unsigned char srvList[6] = {9, -1}; // can be any of 3,5,6,9,10,11 but see above
unsigned char tonList[6] = {11, -1}; // can be any of 3,5,6,9,10,11 but see above
// ...but no pwm on 3 or ll if tone is on
Servo servo[alimit];
void setup() {
if (DEBUG == 1) {
Serial.begin(9600);
}
// setup I2C stuff
Wire.begin(SLAVE_ADDR);
Wire.onRequest(sendData);
Wire.onReceive(receiveData);
strcpy(recvStr, "K");
cdat[0] = '\0';
// init servos and wake them up
for (int i = 0; i < alimit; i++) {
if (srvList[i] == -1) break;
else {
servo[i].attach(srvList[i]);
servo[i].write(5);
delay(500);
servo[i].write(150);
delay(500);
servo[i].write(90);
}
}
//init signal LED
pinMode(flashpin, OUTPUT);
digitalWrite(flashpin, LOW);
delay(200);
digitalWrite(flashpin, HIGH);
delay(200);
digitalWrite(flashpin, LOW);
}
void loop() {
//
// see if there is a command to process
//
if (strcmp(recvStr, "K") != 0) {
// let us know somethings happening
//
DebugOut("Data rcvd:");
DebugOut(recvStr);
//
//do something with received command
if (recvStr[0] == 'S' && strlen(recvStr) >= 4 ) {
char rtmp[6];
int svnum = ((int) (recvStr[1])) - 48;
unsigned char pinOK = pinCheck('s', svnum);
if (pinOK != -1) {
int slew = 90, mflag = 0;
for (int i = 0; i < 6; i++) {
rtmp[i] = recvStr[i+3];
if (rtmp[i] == '\0') break;
if (rtmp[i] == 'm' || rtmp[i] == 'M') {
rtmp[i+1] = '\0';
mflag = 1;
break;
}
}
rtmp[5] = '\0';
slew = atoi(rtmp);
if (mflag && slew > 500 && slew < 2100 ) servo[svnum].writeMicroseconds(slew);
else if (!mflag && slew >= 5 && slew <= 160) servo[svnum].write(slew);
}
} // end of servo slew
if (recvStr[0] == 'M' && strlen(recvStr) >= 4 ) {
char rtmp[6];
int mtnum = ((int) (recvStr[1])) - 48;
unsigned char pinOK = pinCheck('m', mtnum);
if (pinOK != -1) {
int mspeed = 0;
for (int i = 0; i < 6; i++) {
rtmp[i] = recvStr[i+3];
if (rtmp[i] == '\0') break;
}
rtmp[5] = '\0';
mspeed = atoi(rtmp);
if (mspeed >= 0 && mspeed <= 255) {
pinMode(pinOK, OUTPUT);
analogWrite(pinOK, mspeed);
}
}
} // end of motor speed
if (recvStr[0] == 'T' && strlen(recvStr) >= 4 ) {
char rtmp[7];
int newtpin, freq = -2;
unsigned char i = 1, j = 0;
while (j != 99) {
switch (freq) {
case -2:
rtmp[j++] = recvStr[i++];
break;
case -1:
rtmp[j] = '\0';
newtpin = atoi(rtmp);
freq = 0; j = 0;
break;
case 0:
if (recvStr[i] == '\0') {
rtmp[j] = '\0';
if (strlen(rtmp) > 0) freq = atoi(rtmp);
j = 99;
} else rtmp[j++] = recvStr[i++];
break;
}
if (recvStr[i] == '-') {i++; freq = -1;}
}
unsigned char pinOK = pinCheck('t', newtpin);
if (pinOK != -1) {
char dummy[10];
DebugOut("pin:");
DebugOut(itoa(newtpin, dummy, 10));
DebugOut("freq:");
DebugOut(itoa(freq, dummy, 10));
if (freq == 0) { pinMode(newtpin, OUTPUT); noTone(newtpin); }
else { pinMode(newtpin, OUTPUT); tone(newtpin, freq); }
}
} // end of write to digital pin
if (recvStr[0] == 'F' && strlen(recvStr) >= 4 ) {
char rtmp[6];
int newfpin;
for (int i = 0; i < 6; i++) {
rtmp[i] = recvStr[i+3];
if (rtmp[i] == '\0') break;
}
newfpin = atoi(rtmp);
unsigned char pinOK = pinCheck('o', newfpin);
if (pinOK != -1) {
pinMode(newfpin, OUTPUT);
if (recvStr[1] == '0') digitalWrite(newfpin, LOW);
else digitalWrite(newfpin, HIGH);
}
} // end of write to digital pin
// and reset the data for next time 'round..
strcpy(recvStr, "K");
}
}
void DebugOut(char *dbgstr) {
if (DEBUG == 1) {
Serial.println(dbgstr);
}
}
unsigned char pinCheck(char ptype, unsigned char thepin) {
unsigned char res = -1;
switch (ptype) {
case 'i': // digital read
for (int i = 0; i < dlimit; i++) {
if (digiList[i] == -1) break;
else if (digiList[i] == thepin) { res = i; break; }
}
break;
case 'o': // digital write
for (int i = 0; i < dlimit; i++) {
if (digoList[i] == -1) break;
else if (digoList[i] == thepin) { res = i; break; }
}
break;
case 't': // tone output
for (int i = 0; i < dlimit; i++) {
if (tonList[i] == -1) break;
else if (tonList[i] == thepin) { res = i; break; }
}
break;
case 'a': // analog read
for (int i = 0; i < alimit; i++) {
if (algList[i] == -1) break;
else if (algList[i] == thepin) { res = i; break; }
}
break;
case 'm': // pwm output
for (int i = 0; i < alimit; i++) {
if (mtrList[i] == -1) break;
else if (thepin == i) {res = mtrList[i]; break; }
}
break;
case 's': // servo output
for (int i = 0; i < alimit; i++) {
if (srvList[i] == -1) break;
else if (thepin == i) { res = i; break; }
}
break;
default:
res = -1; break;
}
return res;
}
int getSensor(int isens, char sdata[MAXSTR+1]) {
char tstr[5];
// debugging
itoa(isens, tstr, 10);
DebugOut("Data req:");
DebugOut(tstr);
//
if (isens > 96 && isens < 103) {
// read analog pin senscode - 97
unsigned char pinOK = pinCheck('a', isens - 97);
if (pinOK != -1) {
char szdat[MAXSTR + 1] = "\0";
strcpy(sdata, "AV:");
int isdat = analogRead(algList[pinOK]);
itoa(isdat, szdat, 10);
strcat(sdata, szdat);
}
} else if (isens > 64 && isens < 85) {
unsigned char pinOK = pinCheck('i', isens - 65);
if (pinOK != -1) {
int isdat;
char szdat[2];
strcpy(sdata, "DV:");
pinMode(digiList[pinOK], INPUT);
isdat = digitalRead(digiList[pinOK]);
itoa(isdat, szdat, 10);
strcat(sdata, szdat);
}
} else {
strcpy(sdata, "NOP");
}
return strlen(sdata);
}
void receiveData(int thebytes) {
char tstr[2];
tstr[0] = (char) (48 + cmode);
tstr[1] = '\0';
// debugging
DebugOut("I2C recv:");
DebugOut(tstr);
//
while(Wire.available()) {
char c = Wire.read();
int ic = ((unsigned char) c);
switch (cmode) {
case CMD:
switch (c) {
case '1':
cmode = CMD; // check status, sort of a NOP
break;
case '4':
cmode = CGET; // data is coming
break;
case '7':
cmode = WSLCT; // data is wanted from a pin or something
break;
}
break;
case WSLCT:
getSensor(ic, cdat);
ccnt = 0;
cmode = WDATA;
break;
case CGET:
cdat[0] = c;
cdat[1] = '\0';
ccnt = 1;
cmode = CDATA;
break;
case CDATA: {
if (c == '\0') {
ccnt = 0;
strcpy(recvStr, cdat);
cmode = CDEND;
/* flash so we know something worked
digitalWrite(flashpin, LOW);
delay(100);
digitalWrite(flashpin, HIGH);
delay(100);
digitalWrite(flashpin, LOW);
*/
} else {
cdat[ccnt++] = c;
cdat[ccnt] = '\0';
}
break; }
default:
break;
}
}
}
void sendData() {
char tstr[2];
tstr[0] = (char) (48 + cmode);
tstr[1] = '\0';
// debugging
DebugOut("I2C send:");
DebugOut(tstr);
//
switch (cmode) {
case WSLCT:
case CDATA:
case CGET:
case CMD:
Wire.write(cmode + SIG_BASE);
break;
case WDATA: {
int clen = strlen(cdat);
Wire.write(cdat[ccnt]);
ccnt++;
if (ccnt == clen) {
cmode = WDEND;
strcpy(cdat, "\0");
ccnt = 0;
}
break; }
case CDEND:
case WDEND:
Wire.write(cmode + SIG_BASE);
cmode = CMD;
break;
}
}
No comments:
Post a Comment