I2C between RPI and Arduino using Processing - arduino

Posted here is my code for my RPi master and Arduino slave project. I have an analog sensor connected to the Arduino and i am reading this data with Processing on the RPi. I am using Processing because I intend on generating a graph and waveform with the data. The code below seems to work, however, any slight movement of setup "disconnects" the slave device because I get the following message. "The device did not respond. Check the cabling and whether you are using the correct address." I have narrowed the problem down and found out that it always disconnects at the i2c.read();function. My question is whether there is some type of break function so that when this does happen processing moves on and tries again in the next iteration? Or if it is stuck in a loop is it waiting for some signal from the slave device? Does anyone have any suggestions on how to approach this?
Processing Code
import processing.io.*;
I2C i2c;
int val = 0;
void setup()
{
i2c = new I2C(I2C.list()[0]);
}
void draw ()
{
if (I2C.list() != null)
{
i2c.beginTransmission(0x04);
i2c.write(8);
byte[] in = i2c.read(1);
int accel = in[0];
println (accel);
}
}
Arduino Code
#include <Wire.h>
#define SLAVE_ADDRESS 0x04
int number = 5;
int state = 0;
const int zInput = A0;
int zRawMin = 493;
int zRawMax = 530;
float acceleration;
int accel;
void setup() {
analogReference(EXTERNAL);
pinMode(13,OUTPUT);
Serial.begin(9600); // start serial for output
Wire.begin(SLAVE_ADDRESS); // join i2c bus with address #8
Wire.onReceive(receiveData); // register event
Wire.onRequest(sendData);
Serial.println ("Ready");
}
void loop() {
int zRaw = ReadAxis (zInput);
acceleration = map (float(zRaw), float (zRawMin), float(zRawMax), -9.81, 9.81);
accel = int(acceleration);
//delay(100);
}
void receiveData(int byteCount)
{
while (0 < Wire.available())
{ // loop through all but the last
number = Wire.read(); // receive byte as a character
//Serial.print("data received");
Serial.println(number); // print the character
if (number==1)
{
if (state == 0)
{
digitalWrite(13,HIGH);
state = 1;
}
else
{
digitalWrite(13,LOW);
state = 0;
}
}
}
}
void sendData()
{
Wire.write(accel);
}
int ReadAxis(int axisPin)
{
long reading = 0;
int raw = analogRead(axisPin);
return raw;
}

Looks like a solution might be to use a try/catch block courtesy of #Kevin Workman. It works well for what I need it to do thx.
here is the updated Processing code.
import processing.io.*;
I2C i2c;
int val = 0;
void setup()
{
i2c = new I2C(I2C.list()[0]);
}
void draw ()
{
if (I2C.list() != null)
{
i2c.beginTransmission(0x04);
i2c.write(8);
try
{
byte[] in = i2c.read(1);
}
catch(Exception e)
{
i2c.endTransmission();
}
int accel = in[0];
println (accel);
}
}

Related

Send and read the button state via CAN bus using Arduino

I'm intending to read the change of button input using 2 separate Arduino that connected via CAN bus (MP2515). The transmitter will connect to button with internal pulldown resistor, that pin will act as external interrupt. My reference is coming from here. By not assign any value to data frame (canMsg1 and canMsg2 in the code below), is that enough for the receiver to understand the input pin state?
The origin code using digitalRead(pin) to read and later write state of the button by single Arduino.
transmitter of CAN massage
#include <SPI.h>
#include <mcp2515.h>
struct can_frame canMsg1;
struct can_frame canMsg2;
MCP2515 mcp2515(10);
int incPin(2);
int decPin(3);
unsigned long current_time = 0;
unsigned long previous_time = 0;
void setup() {
Serial.begin(9600);
SPI.begin();
mcp2515.reset();
mcp2515.setBitrate(CAN_500KBPS, MCP_8MHZ);
mcp2515.setNormalMode();
canMsg1.can_id = 0xAA;
canMsg1.can_dlc = 1;
canMsg2.can_id = 0xBB
canMsg2.can_dlc = 1;
pinMode(incPin, INPUT_PULLUP);
pinMode(decnPin, INPUT_PULLUP);
attachInterrupt(incpPin, inc, FALLING);
attachInterrupt(decPin, dec, FALLING);
}
void loop() {}
void inc() {
current_time = millis();
if (current_time - previous_time > 200) { //debouncing for 0.2s
mcp2515.sendMessage(&canMsg1);
}
previous_time = current_time;
}
void dec() {
current_time = millis();
if (current_time - previous_time > 200) { //debouncing for 0.2s
mcp2515.sendMessage(&canMsg2);
}
previous_time = current_time;
}
receiver/reader of CAN massage
#include <SPI.h>
#include <mcp2515.h>
struct can_frame canMsg1;
struct can_frame canMsg2;
MCP2515 mcp2515(10);
int pos = 0;
int up;
int down;
void setup() {
Serial.begin(9600);
SPI.begin();
mcp2515.reset();
mcp2515.setBitrate(CAN_500KBPS, MCP_8MHZ);
mcp2515.setNormalMode();
}
void loop() {
if (mcp2515.readMessage(&canMsg1) == MCP2515::ERROR_OK) { //read CAN increment button message
if (canMsg1.can_id==0xAA) {
up = canMsg1.data[0];
if (up == LOW) {
pos++;
} else {}
}
}
if (mcp2515.readMessage(&canMsg2) == MCP2515::ERROR_OK) { //read CAN decrement button message
if (canMsg2.can_id==0xBB) {
down = canMsg2.data[0];
if (down == LOW) {
pos--;
} else {}
}
}
}
You are right, your CAN events do not require any data. But then, why do you set can_dlc to 1? No data is 0 bytes.
You can try this:
Get rid of:
struct can_frame canMsg1; // these only hog global memory for no practical use.
struct can_frame canMsg2;
Change your interrupt routines to:
void inc() {
current_time = millis();
if (current_time - previous_time > 200) { //debouncing for 0.2s
mcp2515.beginPacket(0xAA);
mcp2515.endPacket();
}
previous_time = current_time;
}
void dec() {
current_time = millis();
if (current_time - previous_time > 200) { //debouncing for 0.2s
mcp2515.beginPacket(0xBB);
mcp2515.endPacket();
}
previous_time = current_time;
}
I could not figure out what canMsg7 and canMsg8 were. Nor why you'd need several message structures in global memory to receive one CAN message at a time... I really don't think that's necessary. Since your packets have no data, receiving gets streamlined as well:
int loop() {
if (mcp2515.parsePacket() != 0) { // != 0 => we have fully received a packet.
switch (mcp2515.packetId()) {
case 0xAA:
// inc switch was pressed
// ...
break;
case 0xBB:
// dec switch was pressed
// ...
break;
}
}
}

How to send Bluetooth data from ESP32 in arduino?

Easy to handle received data with BLE but can't send data.
I'm using ESP32 BLE Uart code.
It's easy to get data from RxCharateristic but I don't know how to send data.
I'm trying to use TxCharacteristic to send data with BLE.
#include <BLEDevice.h>
#include <BLEServer.h>
#include <BLEUtils.h>
#include <BLE2902.h>
BLEServer *pServer = NULL;
BLECharacteristic * pTxCharacteristic;
bool deviceConnected = false;
bool oldDeviceConnected = false;
uint8_t txValue = 0;
// See the following for generating UUIDs:
// https://www.uuidgenerator.net/
#define SERVICE_UUID "6E400001-B5A3-F393-E0A9-E50E24DCCA9E" // UART service UUID
#define CHARACTERISTIC_UUID_RX "6E400002-B5A3-F393-E0A9-E50E24DCCA9E"
#define CHARACTERISTIC_UUID_TX "6E400003-B5A3-F393-E0A9-E50E24DCCA9E"
class MyServerCallbacks: public BLEServerCallbacks {
void onConnect(BLEServer* pServer) {
deviceConnected = true;
};
void onDisconnect(BLEServer* pServer) {
deviceConnected = false;
}
};
class MyCallbacks: public BLECharacteristicCallbacks {
void onWrite(BLECharacteristic *pCharacteristic) {
std::string rxValue = pCharacteristic->getValue();
if (rxValue.length() > 0) {
Serial.println("*********");
Serial.print("Received Value: ");
for (int i = 0; i < rxValue.length(); i++){
Serial.print(rxValue[i]);
}
}
}
};
void setup() {
Serial.begin(115200);
// Create the BLE Device
BLEDevice::init("TheOneSystem");
// Create the BLE Server
pServer = BLEDevice::createServer();
pServer->setCallbacks(new MyServerCallbacks());
// Create the BLE Service
BLEService *pService = pServer->createService(SERVICE_UUID);
// Create a BLE Characteristic
pTxCharacteristic = pService->createCharacteristic(
CHARACTERISTIC_UUID_TX,
BLECharacteristic::PROPERTY_NOTIFY
);
pTxCharacteristic->addDescriptor(new BLE2902());
BLECharacteristic * pRxCharacteristic = pService->createCharacteristic(
CHARACTERISTIC_UUID_RX,
BLECharacteristic::PROPERTY_WRITE
);
pRxCharacteristic->setCallbacks(new MyCallbacks());
// Start the service
pService->start();
// Start advertising
pServer->getAdvertising()->start();
Serial.println("Waiting a client connection to notify...");
}
void loop() {
if (deviceConnected) {
pTxCharacteristic->setValue(&txValue, 1);
pTxCharacteristic->notify();
txValue++;
delay(10); // bluetooth stack will go into congestion, if too many packets are sent
}
// disconnecting
if (!deviceConnected && oldDeviceConnected) {
delay(500); // give the bluetooth stack the chance to get things ready
pServer->startAdvertising(); // restart advertising
Serial.println("start advertising");
oldDeviceConnected = deviceConnected;
}
// connecting
if (deviceConnected && !oldDeviceConnected) {
// do stuff here on connecting
oldDeviceConnected = deviceConnected;
}
}
I can easily handle received data with this part of code
class MyCallbacks: public BLECharacteristicCallbacks {
String bleData;
void onWrite(BLECharacteristic *pCharacteristic) {
std::string rxValue = pCharacteristic->getValue();
if (rxValue.length() > 0) {
Serial.println("*********");
Serial.print("Received Value: ");
for (int i = 0; i < rxValue.length(); i++){
//Serial.print(rxValue[i]);
bleData=bleData+rxValue[i];
}
Serial.println();
Serial.println(bleData);
Serial.println("*********");
int first = bleData.indexOf(",");
String bleSSID = bleData.substring(0, first);
String blepw = bleData.substring(first+1, bleData.length());
Serial.println("Wifi : " + bleSSID + "," + "Password : " + blepw);
bleData="";
}
}
};
How to send data by using TxCharacteristic?
In my receiving code, I'm using this function to use callback.
if(pTxCharacteristic->canNotify()) {
pTxCharacteristic->registerForNotify(notifyCallback);
}
And here is my notifyCallback function i got from Google.
static void notifyCallback(
BLERemoteCharacteristic* pBLERemoteCharacteristic,
uint8_t* pData,
size_t length,
bool isNotify){
Serial.println(data);
}
It seems like i have to add a little function in notifyCallback.
However errors continue to occur. I can't get data. Tnx for help.

Receiving whole string in uart sending data

I connect my NodeMCU to Arduino Uno. The goal is to receive the whole string for example "12", every 1 sec.
This is my code on Arduino Uno side ( the sender)
int mock = 0;
void setup() {
Serial.begin(115200);
s.begin(115200);
}
void loop() {
//Write mock to NodeMCU
s.print((int)mock,DEC);
s.println();
mock++;
delay(1000);
}
On NodeMCU side ( the receiver)
char data; //Initialized variable to store recieved data
String line;
void setup() {
Serial.begin(115200);
s.begin(115200);
while (!Serial) {
;
}
}
void loop() {
if( s.available() >= 2) {
for (int i = 0; i< 2; i++ ) {
data = s.read();
line += data;
}
delay(1000);
}
Serial.print(line);
}
But the result on the serial panel is not what I expected
[![Serial terminal][1]][1]
https://i.stack.imgur.com/NGC3k.png
How can I make it so that I can receive something like
12
(wait one sec)
13
(wait one sec)
....
Node MCU just prints the whole thing, I can't delay it.

How to send a number over serial to an arduino?

I'm trying to send a number value over serial to an Arduino to control an Individually Addressable LEDstrip. Using the Arduino IDE "Serial Monitor" I'm able to send a number to the light strip with no issue. However when i try to do it externally by reading from a text file in processing it doesn't go through.
After some debugging I can see that Processing has the number right and its stored in the variable. However the lightstip will only ever light up on led, instead of the number given.
Processing Code:
import processing.serial.*;
import java.io.*;
Serial myPort; // Create object from Serial class
void setup()
{
size(200,200); //make our canvas 200 x 200 pixels big
String portName = Serial.list()[0]; //change the 0 to a 1 or 2 etc. to match your port
myPort = new Serial(this, portName, 9600);
}
void draw()
{
while(true) {
// Read data from the file
{
String[] lines = loadStrings("Lifenumber.txt");
int number = Integer.parseInt(lines[0]);
println(number);
myPort.write(number);
delay(5000);
}
}
}
Arduino Code:
if ( Serial.available()) // Check to see if at least one character is available
{
char ch = Serial.read();
if(index < 3 && ch >= '0' && ch <= '9'){
strValue[index++] = ch;
}
else
{
Lnum = atoi(strValue);
Serial.println(Lnum);
for(i = 0; i < 144; i++)
{
leds[i] = CRGB::Black;
FastLED.show();
delay(1);
}
re = 1;
index = 0;
strValue[index] = 0;
strValue[index+1] = 0;
strValue[index+2] = 0;
}
}
What I want the program to do is read a number from a text file and light up that number of LEDs on the 144led lightstrip.
Here are a couple of comments on your code that should help make improvements in the future. It's important to form good coding habits early on: it will make your life so much easier (I'm speaking a mostly self taught programmer that started with flash so I know what messy and hacky is ;) )
import processing.serial.*;
//import java.io.*; // don't include unused imports
Serial myPort; // Create object from Serial class
void setup()
{
size(200,200); //make our canvas 200 x 200 pixels big
String portName = Serial.list()[0]; //change the 0 to a 1 or 2 etc. to match your port
// handle error initialising Serial
try{
myPort = new Serial(this, portName, 9600);
}catch(Exception e){
println("Error initializing Serial port " + portName);
e.printStackTrace();
}
}
void draw()
{
// don't use blocking while, draw() already gets called continuously
//while(true) {
// Read data from the file
//{
// don't load the file over and over again
String[] lines = loadStrings("Lifenumber.txt");
int number = Integer.parseInt(lines[0]);// int(lines[0]) works in Processing, but the Java approach is ok too
println("parsed number: " + number);
if(myPort != null){
myPort.write(number);
}
// don't use blocking delays, ideally not even in Arduino
//delay(5000);
//}
//}
}
Here's a version of the Processing code that loads the text file, parses the integer then sends it to serial only once (if everything is ok, otherwise basic error checking should reveal debug friendly information):
import processing.serial.*;
Serial myPort; // Create object from Serial class
void setup()
{
size(200,200); //make our canvas 200 x 200 pixels big
String portName = Serial.list()[0]; //change the 0 to a 1 or 2 etc. to match your port
// handle error initialising Serial
try{
myPort = new Serial(this, portName, 9600);
}catch(Exception e){
println("Error initializing Serial port " + portName);
e.printStackTrace();
}
// Read data from the file
try{
String[] lines = loadStrings("Lifenumber.txt");
int number = Integer.parseInt(lines[0]);
println("parsed number: " + number);
// validate the data, just in case something went wrong
if(number < 0 && number > 255){
println("invalid number: " + number + ", expecting 0-255 byte sized values only");
return;
}
if(myPort != null){
myPort.write(number);
}
}catch(Exception e){
println("Error loading text file");
e.printStackTrace();
}
}
void draw()
{
// display the latest value if you want
}
// add a keyboard shortcut to reload if you need to
Your strip has 144 leds (less than 255) which fits nicely in a single byte which is what the Processing sketch sends
On the Arduino side there's nothing too crazy going on, so as long as you validate the data coming in should be fine:
#include "FastLED.h"
#define NUM_LEDS 64
#define DATA_PIN 7
#define CLOCK_PIN 13
// Define the array of leds
CRGB leds[NUM_LEDS];
int numLEDsLit = 0;
void setup() {
Serial.begin(9600);
Serial.println("resetting");
LEDS.addLeds<WS2812,DATA_PIN,RGB>(leds,NUM_LEDS);
LEDS.setBrightness(84);
}
void loop() {
updateSerial();
updateLEDs();
}
void updateSerial(){
// if there's at least one byte to read
if( Serial.available() > 0 )
{
// read it and assign it to the number of LEDs to light up
numLEDsLit = Serial.read();
// constrain to a valid range (just in case something goes funny and we get a -1, etc.)
numLEDsLit = constrain(numLEDsLit,0,NUM_LEDS);
}
}
// uses blacking delay
void updateLEDs(){
// for each LED
for(int i = 0; i < 144; i++)
{
// light up only the number of LEDs received via Serial, turn the LEDs off otherwise
if(i < numLEDsLit){
leds[i] = CRGB::White;
}else{
leds[i] = CRGB::Black;
}
FastLED.show();
delay(1);
}
}
Adjust the pins/LED chipsets/etc. based on your actual physical setup.

Making a Game With Arduino and Processing

I am trying to form a two player game which requires an audio reflex to a visual. by using littebits sound trigger for sound input and littbits arduino to connect it to the computer. But I am new to this and don't know how to connect arduino to processing and use the input from sound trigger to effect the score when a black square appears.
here is my code in processing and a sample arduino code I have taken from littlebits website and tried to modify a little.
thanks in advance!
float dice;
int playerOne = 0; //player 1 score (left paddle)
int playerTwo = 0; //player 2 score (right paddle)
boolean oneWins = false;
boolean twoWins = false;
void setup(){
size(500, 500);
smooth();
noStroke();
frameRate(2.5);
}
void draw() {
background(255);
showGUI();
dice = random(0, 3);
if (dice < 1.000001 && dice > 0.1){
fill ((0), (255), (0));
ellipse (250,250,100,100);
} else if (dice < 2.000001 && dice > 1.000001){
rectMode(RADIUS);
fill ((255), (0), (0));
rect (250,250,50,50);
} else if (dice < 3.000000 && dice > 1.000000){
rectMode(RADIUS);
fill ((0), (0), (255));
rect (250,250,50,50);
} else if (dice < 0.1){
rectMode(RADIUS);
fill(0);
rect(250,250,50,50);
}
}
----------arduino------
void setup() {
Serial.begin(9600); //Establish rate of Serial communication
establishContact(); //See function below
}
void loop() {
if (Serial.available() > 0) {
int inByte = Serial.read();
int leftTrigger = analogRead(A0);
Serial.print(leftTrigger, DEC);
Serial.print(",");
int rightTrigger = analogRead(A1);
Serial.println(rightTrigger, DEC);
}
}
void establishContact() {
while (Serial.available() <= 0) {
Serial.println("hello");
delay(300);
}
}
You need two pieces of code for this to work: one on the Arduino that sends commands, and one for Processing to receive and parse those commands.
I haven't used the littlebits modules, but here's a button example from this very detailed tutorial.
Arduino code:
int switchPin = 4; // switch connected to pin 4
void setup() {
pinMode(switchPin, INPUT); // set pin 0 as an input
Serial.begin(9600); // start serial communication at 9600bps
}
void loop() {
if (digitalRead(switchPin) == HIGH) { // if switch is ON,
Serial.print(1, BYTE); // send 1 to Processing
} else { // if the switch is not ON,
Serial.print(0, BYTE); // send 0 to Processing
}
delay(100); // wait 100 milliseconds
}
And the matching Processing code:
import processing.serial.*;
Serial port; // create object from Serial class
int val; // data received from the serial port
void setup() {
size(200, 200);
frameRate(10);
// open the port that the board is connected to
// and use the same speed (9600bps)
port = new Serial(this, 9600);
}
void draw() {
if (0 < port.available()) { // if data is available,
val = port.read(); // read it and store it in val
}
background(255); // set background to white
if (val == 0) { // if the serial value is 0,
fill(0); // set fill to black
} else { // if the serial value is not 0,
fill(204); // set fill to light gray
}
rect(50, 50, 100, 100);
}
Notice that the Arduino sends a value that Processing looks for and interprets. You can also look at the PhysicalPixel example from the Arduino IDE for an example on sending data from Processing to Arduino.

Resources