I have an app that I am writing three strings to EEPROM. The strings are from when the user first starts the app. They are from "WiFiManager".
code
WiFiManager wifiManager;
WiFiManagerParameter customAPIKey("authorizationKey", "Authorization Code", authorizationKey, 32);
WiFiManagerParameter customAPIKey2("apiKey", "Time Zone #", apiKey, 32);
WiFiManagerParameter customAPIKey3("userNameKey", "User Name",userNameKey, 32);
wifiManager.addParameter(&customAPIKey);
wifiManager.addParameter(&customAPIKey2);
wifiManager.addParameter(&customAPIKey3);
wifiManager.autoConnect("FloWT3");
Serial.println("Connected");
strcpy(authorizationKey, customAPIKey.getValue());
strcpy(apiKey, customAPIKey2.getValue());
strcpy(userNameKey, customAPIKey3.getValue());
So this is when the app starts up if it can't connect to the internet it opens up a local access point "FloWT3" and the user fills in the local WiFi Name, Password, MQTT authorizationKey, Time Offset, and MQTT Username.
WiFi manager automatically stores the WiFi Name and Password and I store the other three in EEPROM with this code;
This is all in void setup()
Then in void loop()
WiFiManager wifiManager;
//if the wifi is not connected I open "FloWT3" access point again.
if (WiFi.status() == WL_DISCONNECTED) {
wifiManager.autoConnect("FloWT3");
delay(60000);}
//but if it is connected I access EEPROM and read what has been read.
else if (WiFi.status() == WL_CONNECTED) { Serial.println("Connected");
delay(2000);
WiFiClient client;
EEPROM.begin(512); //Initialize EEPROM
//This is where I moved the code to and added if statement.
String rrr = apiKey;
if (rrr.length()==0){
Serial.println("empty"):
}
else {
Serial,println("not empty");
//Write string to eeprom
String uuu = authorizationKey;
Serial.print("uuu");
Serial.print(uuu);
String www = apiKey;//Homenetwork + uuu;
Serial.print("www");
Serial.print(www);
String yyy = userNameKey;
String fff = String(www)+String(",");
String vvv = String(yyy)+String(",");
Serial.print("vvv");
Serial.print(vvv);
for(int i=0;i<uuu.length();i++) //loop upto string lenght www.length() returns length of string
{
EEPROM.write(0x0F+i,uuu[i]); //Write one by one with starting address of 0x0F
}
for(int i=0;i<fff.length();i++) //loop upto string lenght www.length() returns length of string
{
EEPROM.write(0x50+i,fff[i]); //Write one by one with starting address of 0x0F
}
for(int i=0;i<vvv.length();i++) //loop upto string lenght www.length() returns length of string
{
EEPROM.write(0x90+i,vvv[i]); //Write one by one with starting address of 0x0F
}
EEPROM.commit(); //Store data to EEPROM
}
delay (500);
String www;
//here I read the first part I wrote to address 0x0F which is the authorizationKey
for(int i=0;i<32;i++)
{
www = www + char(EEPROM.read(0x0F+i)); //Read one by one with starting address of 0x0F
}
//here is read from the address 0X50 which I wrote the apiKey (time offset)
String uuu;
for(int i=0;i<32;i++)
{uuu = uuu + char(EEPROM.read(0x50+i));
}
//here I read from address 0x090+i where I wrote the userNameKey
String vvv;
for(int i=0;i<32;i++)
{vvv = vvv + char(EEPROM.read(0x90+i));
}
Serial.println("this");
Serial.print(www);
Serial.println("that");
Serial.print(uuu);
Serial.println("those");
Serial.print(vvv);
When I program the ESP8266-01 the first time so the user has to fill in the info in the "FloWT3" access point these are the reading I get on the Serial Monitor
this
11:35:13.576 -> aio_XXXXXXXXXXXXXXXXXXXXXXXXXXXthat
11:35:13.576 -> -07,⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮those
11:35:13.576 -> XXXXXXX,⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮
This is as expected and everything works fine.
Now when I run the app and it connects with the stored information I get these reading which are the same
this
11:35:13.576 -> aio_XXXXXXXXXXXXXXXXXXXXXXXXXXXthat
11:35:13.576 -> -07,⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮those
11:35:13.576 -> XXXXXXX,⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮
I can now split out the parts I need using indexOf(",") and substrings. Everything is working very well.
I am thankful to hcheung for the suggestion and I will study up more on strcpy.
I found the reason for the replacement ,s. When the app open and ran it wrote a blank string to the beginning of the EEPROMs thus overriding the first character. So I moved the write part of the EEPROM into the if(WiFi.status() == WL_CONNECTED and also checked to see if the length of a String from the apiKey was equal to 0 or not. If it was 0 then the info was already stored in the EEPROM and didn't need to be written again. If it had a length then the app was being set up for the first time and writing to EEPROM needed to happen. I have changed my original post to reflect these changes.
Related
I have an MPU6050 gyroscope and accelerometer connected with Arduino through the I2C protocol. These sensor send a continuos stream of data into the Serial port with these instructions (in the arduino IDE):
Serial.print(euler[0] * 180/M_PI);
Serial.print(":");
Serial.print(euler[1] * 180/M_PI);
Serial.print(":");
Serial.println(euler[2] * 180/M_PI);
This come from an example sketch included in the library of the sensor and it just sends the value of yaw / pitch / roll to the serial port, separated by the colon.
Now there is the interesting part. I've always been fascinated about visualizing data, and so i want to build a sort of graph of these data coming from serial in Processing(this is part of a larger project that include a ultrasonic sensor, like a sort of radar).
So I wrote a short sketch on processing to catch that data in order to analyze and visualize it. This is the sketch:
import processing.serial.*;
Serial myPort;
String data; //Angle values
String[] splitted; //Array containing splitted data
float yaw, pitch , roll;
void setup()
{
myPort = new Serial (this, Serial.list()[0], 115200);
}
void draw()
{
while (myPort.available() > 0) //data arrived fromm serial
{
data = myPort.readStringUntil('\n');
//Data Parsing
splitted = data.split(":");
yaw = float(splitted[0]);
pitch = float(splitted[1]);
roll = float(splitted[2]);
println(yaw + " " + pitch + " " + roll);
}
}
This code doesn't work. There are 2 errors that alternate. One of them is:
ArrayIndexOutOfBondsException
And the other one:
NullPointerException
That points to the "splitted" array.
I think i got the problem. In a previous version of the Processing sketch i was using the:
readString() function
I think that, since data are sent to the Serial port in the Arduino sketch one at a time, the processing sketch sometimes catch only one, or two of the yaw, pitch, roll values, causing the array index to crash or to a nullPointerexception when no value is added to the array. I then changed the '''readString''' to the '''readStringUntil('\n')''', because, maybe the first packet will be lost but the other one coming next will always be cathed without breaking them (i catch the entire line). But there are the same errors, so I think my small experience can't help solving the problem anymore. I need your help.
Excuse me for my bad English, and thanks for any help.
You are on the right track. Here are a few pointers:
you can use a try/catch block so the sketch doesn't simply crash on an error
you can use bufferUntil() to tell the serial library to buffer bytes for you until a new line is encountered: it works well in tandem with serialEvent() which gets called automatically (so you don't need to use a while loop that would block rendering/the rest of the sketch)
you can check (and should) anything that could go wrong with the data (null string, empty string, not enough values within the string, etc.)
Here's a modified version of your sketch:
import processing.serial.*;
Serial myPort;
float yaw, pitch , roll;
void setup()
{
String[] portNames = Serial.list();
// skipp serial setup if there are no ports
if(portNames.length == 0){
println("no serial ports found");
return;
}
// try to open serial port, handle error
try
{
myPort = new Serial (this, portNames[0], 115200);
// buffer bytes(characters) until new line is hit
myPort.bufferUntil('\n');
}
catch(Exception e)
{
println("error opening port: " + portNames[0]);
println("double check the port is present and not used by other applications (e.g. SerialMonitor)");
e.printStackTrace();
}
}
void draw()
{
background(0);
text(String.format("yaw: %.2f \npitch: %.2f \nroll: %.2f", yaw, pitch, roll), 5, 15);
}
// serialEvent gets called when there's new data: no need an explicit blocking while loop
void serialEvent(Serial port){
try
{
// read string from serial
String rawSerialString = port.readString();
// exit on null string
if(rawSerialString == null)
{
println("received null string, skipping this serial message");
return;
}
// exit on empty string
if(rawSerialString.length() == 0)
{
println("received empty string, skipping this serial message");
return;
}
// trim white space (\r, \n, etc.)
rawSerialString = rawSerialString.trim();
// split and convert to float
float[] rotations = float(rawSerialString.split(":"));
// exit if message got jumbled up and values are missing
if(rotations.length < 3)
{
println("received less than 3 values, skipping this serial message");
return;
}
// finally extract values
yaw = rotations[0];
pitch = rotations[1];
roll = rotations[2];
println(yaw + " " + pitch + " " + roll);
}
catch(Exception e)
{
println("error reading/parsing serial data");
e.printStackTrace();
}
}
Obviously you receive lines with less than two colons.
Hard to tell from here what you should do then, but checking the length of the splitted array were the first step anyway. Either via if or as an Exception.
I have a project in which I use an Arduino UNO and an esp8266-01.
The Arduino is used to gather water high and water low sensor information and then transmit that information over to turn on/off a latching relay for a water valve to fill my pool. It also turns off and on a solar panel to charge my batteries and also turns off and on the esp8266.
I want to be able to connect to the wifi every time the esp8266 comes on and then send water level sensor information and battery level sensor information up to thingSpeak.
In the following code I have made it so that the first time the esp8266 is powered up it tries to connect to the local wifi but since no ip and password is provided it go to access point mode and opens a sign in page. I also provide the user to input their thingSpeak write api. This data is saved to the esp8266's eeprom so that in the future it will auto connect and send information to thingSpeak. This works fine.
My problem is getting the information from the water level sensor and the battery level into the esp8266. I was first gathering the data on the Arduino and then having the esp8266 connect and upload the information using AT commands using SerialSoftware. However to get the AUTOCONNECT to work I had to reprogram the esp8266 and now it doesn't respond to AT commands. I have tried to reprogram the RX and TX pins on the ESP but it only has two reading when there is water present it reads 1024 and no water is 0. Nothing in between. The battery level doesn't register anything. Can I do this using the TX and RX pins somehow as an analog input or can I take the information (numbers) gathered on the Arduino and had them off to the ESP8266 using the TX (arduino) and RX (ESP)to send them to ThingSpeak. I am at a loss and need help.
Here is the code on the ESP8266
#include <FS.h>
#include <ESP8266WiFi.h> //https://github.com/esp8266/Arduino
#include <EEPROM.h>
//needed for library
#include <DNSServer.h>
#include <ESP8266WebServer.h>
#include <WiFiManager.h> //https://github.com/tzapu/WiFiManager
#include <ArduinoJson.h>
//NEW STUFF START
char Password[36]="";
char apiKey[16]="";
WiFiClient client;
//eeprom new end
char defaultHost[100] = ""; //Thing Speak IP address (sometime the web address causes issues with ESP's :/
long itt = 500;
long itt2 = 500;
const byte wifiResetPin = 13;
int interruptPinDebounce = 0;
long debouncing_time = 1000;
volatile unsigned long wifiResetLastMillis = 0;
bool shouldSaveConfig = false;
void saveConfigCallback () {
Serial.println("Should save config");
shouldSaveConfig = true;}
void handleWifiReset(){
if(millis()<wifiResetLastMillis){
wifiResetLastMillis = millis();
}
if((millis() - wifiResetLastMillis)>= debouncing_time){
Serial.println("Clearing WiFi data resetting");
WiFiManager wifiManager;
wifiManager.resetSettings();
SPIFFS.format();
ESP.reset();
delay(1000);
}
wifiResetLastMillis = millis();
}
int addr = 0;
void setup() {
//EEPROM.begin(512); //Initialize EEPROM
WiFiManager wifiManager;
// put your setup code here, to run once:
Serial.begin(115200);
pinMode(wifiResetPin, INPUT_PULLUP);
attachInterrupt(digitalPinToInterrupt(wifiResetPin), handleWifiReset,FALLING);
WiFiManagerParameter customAPIKey("apiKey", "ThingSpeakWriteAPI", apiKey, 16);
//END NEW STUFF
//WiFiManager
//Local intialization. Once its business is done, there is no need to keep it around
//WiFiManager wifiManager;
//NEW STUFF START
//wifiManager.setSaveConfigCallback(saveConfigCallback);
wifiManager.addParameter(&customAPIKey);
//END NEW STUFF
//reset saved settings
//wifiManager.resetSettings();
//set custom ip for portal
//wifiManager.setAPStaticIPConfig(IPAddress(10,0,1,1), IPAddress(10,0,1,1), IPAddress(255,255,255,0));
//fetches ssid and pass from eeprom and tries to connect
//if it does not connect it starts an access point with the specified name
//here "AutoConnectAP"
//and goes into a blocking loop awaiting configuration
wifiManager.autoConnect("AutoConnectAP");
Serial.println("Connected");
//NEW STUFF START
strcpy(apiKey, customAPIKey.getValue());
if (shouldSaveConfig) {
Serial.println("saving config");
DynamicJsonBuffer jsonBuffer;
JsonObject& json = jsonBuffer.createObject();
json["defaultHost"] = defaultHost;
json["apiKey"] = apiKey;
Serial.println("API");
Serial.print(apiKey);
String apiKey2 = String(apiKey);
File configFile = SPIFFS.open("/config.json", "w");
if (!configFile) {
Serial.println("failed to open config file for writing");
}
json.printTo(configFile);
json.printTo(Serial);
delay(1000);
configFile.close();
//end save
}
Serial.println("local ip");
Serial.println(WiFi.localIP());
//END NEW STUFF
//or use this for auto generated name ESP + ChipID
//wifiManager.autoConnect();
//Serial.println("WriteApi");
//Serial.println(apiKey);
//if you get here you have connected to the WiFi
//Serial.println("K)");
//save the custom parameters to FS
strcpy(apiKey,customAPIKey.getValue());
EEPROM.begin(512); //Initialize EEPROM
// write appropriate byte of the EEPROM.
// these values will remain there when the board is
// turned off.
EEPROM.write(addr, 'A'); //Write character A
addr++; //Increment address
EEPROM.write(addr, 'B'); //Write character A
addr++; //Increment address
EEPROM.write(addr, 'C'); //Write character A
//Write string to eeprom
String www = apiKey;
for(int i=0;i<www.length();i++) //loop upto string lenght www.length() returns length of string
{
EEPROM.write(0x0F+i,www[i]); //Write one by one with starting address of 0x0F
}
EEPROM.commit(); //Store data to EEPROM
//Read string from eeprom
}
//callback notifying us of the need to save config
void loop() {
Serial.begin(115200);
WiFiManager wifiManager;
if (WiFi.status() == WL_DISCONNECTED) {
wifiManager.autoConnect("AutoConnectAP");}
delay(5000);
if (WiFi.status() == WL_CONNECTED) { Serial.println("Connected");
WiFiClient client;
long itt = 500;
long itt2 = 500;
char defaultHost[100] = "api.thingspeak.com";
//HERE IS WHERE I CHANGE THE TX AND RX PIN FUNCTION
pinMode(1, FUNCTION_3);
pinMode(3, FUNCTION_3);
//THEN I ASSIGN THEM AS INPUT PINS
pinMode(1,INPUT);
pinMode(3,INPUT);
//ASSIGN EACH PIN TO AN INTERGER
const int waterInPin = 3; // Analog input pin that the potentiometer is attached to
const int BatteryInPin = 1; // Analog input pin that the battery is attached to
int waterSensorInValue;//reading our water lever sensor
int waterSensorOutValue;//conversion of water sensor value
int BatterySensorInValue;//reading our water lever sensor
int BatterySensorOutValue;//conversion of water sensor value
// put your main code here, to run repeatedly:
waterSensorInValue = analogRead(waterInPin);
BatterySensorInValue = analogRead(BatteryInPin);
waterSensorOutValue = map(waterSensorInValue,0,1024,0,225);
BatterySensorOutValue = map(BatterySensorInValue,0,1024,0,225);
Serial.println("WaterOutValue = ");
Serial.println(waterSensorOutValue );
Serial.println("WaterInValue = ");
Serial.println(waterSensorInValue );
Serial.println("BatteryOutValue = ");
Serial.println(BatterySensorOutValue );
Serial.println("BatteryInValue = ");
Serial.println(BatterySensorInValue);
//ASSIGN THE INPUT VALUES TO UPLOAD LONGS
itt = waterSensorInValue;
itt2 = BatterySensorInValue;
EEPROM.begin(512);
Serial.println(""); //Goto next line, as ESP sends some garbage when you reset it
Serial.print(char(EEPROM.read(addr))); //Read from address 0x00
addr++; //Increment address
Serial.print(char(EEPROM.read(addr))); //Read from address 0x01
addr++; //Increment address
Serial.println(char(EEPROM.read(addr))); //Read from address 0x02
//Read string from eeprom
String www;
//Here we dont know how many bytes to read it is better practice to use some terminating character
//Lets do it manually www.circuits4you.com total length is 20 characters
for(int i=0;i<16;i++)
{
www = www + char(EEPROM.read(0x0F+i)); //Read one by one with starting address of 0x0F
}
Serial.print(www); //Print the text on serial monitor
if (client.connect(defaultHost,80))
{ // "184.106.153.149" or api.thingspeak.com
itt++; //Replace with a sensor reading or something useful
//UPLOAD TO THINGSPEAK
String postStr = www;
postStr +="&field1=";
postStr += String(itt);
postStr +="&field2=";
postStr += String(itt2);
postStr += "\r\n\r\n\r\n";
client.print("POST /update HTTP/1.1\n");
client.print("Host: api.thingspeak.com\n");
client.print("Connection: close\n");
client.print("X-THINGSPEAKAPIKEY: "+String (www)+"\n");
client.print("Content-Type: application/x-www-form-urlencoded\n");
client.print("Content-Length: ");
client.print(postStr.length());
client.print("\n\n\n");
client.print(postStr);
Serial.println("% send to Thingspeak");
}
client.stop();
Serial.println("Waiting…");
}
delay(55000);
}
As I said almost everything works ok. The ESP8266 comes on when the Arduino turns it on. The sensor comes on and gets the value. A value is uploaded to ThingSpeak (just not a useful one.
Any Ideas, suggestions, examples, tutorials will be greatly appreciated. Thanks.
My suggestion is use only one ESP32 to do all this work.
It´s much simpler and easier than using two micro-controllers.
You can use the ESP32 to read and send the sensor data and save the trouble of communicating two different micros.
I've been trying to get a piece of code that sends a text message to a phone when an IFTTT applet site is visited, I've been following this tutorial regarding the text message itself and this one for the WiFi shield for the ability to connect to a webpage and an HTTP request.
Basically, my problem is that it will connect to any "simple" site like google.com but it can't for "longer/complex" links. I was wondering if you would have any idea how would I solve this problem and get this to work. I've tried just using the addition symbol to combine the "simple" link and the rest of my desired link but that doesn't work either.
#include <SoftwareSerial.h> // Include software serial library, ESP8266 library dependency
#include <SparkFunESP8266WiFi.h> // Include the ESP8266 AT library
void setup() {
Serial.begin(9600);
String url = "/trigger/ESP/with/key/dwSukgpyQsyampQMkXXXX";
Serial.print (url);
// put your setup code here, to run once:
if (esp8266.begin()) // Initialize the ESP8266 and check it's return status
Serial.println("ESP8266 ready to go!"); // Communication and setup successful
else
Serial.println("Unable to communicate with the ESP8266 :(");
int retVal;
retVal = esp8266.connect("network", "networkpassword");
if (retVal < 0)
{
Serial.print(F("Error connecting: "));
Serial.println(retVal);
}
IPAddress myIP = esp8266.localIP(); // Get the ESP8266's local IP
Serial.print(F("My IP is: ")); Serial.println(myIP);
ESP8266Client client; // Create a client object
retVal = client.connect("maker.ifttt.com" + url, 80); // Connect to sparkfun (HTTP port)
if (retVal > 0)
Serial.println("Successfully connected!");
client.print("GET / HTTP/1.1\nHost: maker.ifttt.com" + url + "\nConnection: close\n\n");
while (client.available()) // While there's data available
Serial.write(client.read()); // Read it and print to serial
}
void loop() {
// put your main code here, to run repeatedly:
}
Thanks, any help would be very much appreciated!
First, the connect function requires a server(name) to connect to. In your case: maker.ifttt.com. Anything after the .com will make the connection fail (because it's not a correct servername).
Second: this function needs an IP address (like 54.175.81.255) or an array of characters. You cannot concatenate.
After you've established the connection, you can send and receive data to a specific part of this website, using the print function.
Also, in this function you can't concatenate.
Luckily, there is a String class where we easily can concatenate.
So, after you've created the client object (ESP8266Client client;), this could be the code:
String url;
char host[] = "maker.ifttt.com";
retVal = client.connect(host, 80);
if (retVal > 0) {
Serial.println("Successfully connected!");
}
url = "GET / HTTP/1.1\r\nHost: ";
url += host;
url += "/trigger/ESP/with/key/dwSukgpyQsyampQMkXXXX";
url += "\nConnection: close\n\n";
client.print(url);
while (client.connected() && !client.available());
while (client.available()) {
Serial.write(client.read());
}
I have an arduino-processing communication problem.
I have arduino code that gives me X-and/Y coordinates from a touchScreen
and it works well, no problem with that, I got my X- and Y coordinates.
BUT I need to visualize that, I am trying to write code in Processing 3.0, so that I will be able to see on my computer, where the touchFolie was being touched.
So I need to send the x-y from arduino to processing so that I will be able to draw.
Does anyone know how can I send an integer array[X,Y] from arduino to processing ??
It will be helpful to have a play with the Serial library in Processing and the SerialRead example (in Processing > File > Examples > Libraries > serial > SimpleRead)
Let's say you're starting from scratch.
To send data from Arduino you need to open a Serial connection.
At this stage the only important details is the baud rate: how fast is the data flowing.
Here's a minimal Arduino data out example:
void setup() {
//initialize the Serial library with baud rate 115200
Serial.begin(115200);
}
void loop() {
//write data to the serial port
Serial.println("test");
delay(1000);
}
If you open Serial Monitor in the Arduino software and set the baud rate to 115200 you should see test printed once a second.
To read the same data in Processing, aside from specifying the baud rate, you must also specify the serial port (what you have selected in Tools > Port and is also listed at the bottom right of your current Arduino sketch):
import processing.serial.*;
void setup() {
//update the serial port index based on your setup
println(Serial.list());
Serial arduino = new Serial(this, Serial.list()[0], 115200);
arduino.bufferUntil('\n');
}
void draw() {
}
void serialEvent(Serial p) {
//read the string from serial
String rawString = p.readString();
println(rawString);
}
Notice that we tell Processing to buffer until it reaches a '\n' character so we don't have to worry about waiting for every single character and append it manually to a String. Instead using bufferUntil(), serialEvent() and readString() most of the work is done for us.
Now that you can send a String from Arduino and read it in Processing, you can do some String manipulation, like splitting a string into multiple using a separator via the split() function:
String xyValues = "12,13";
printArray(xyValues.split(","));
The last part would be converting the split values from String to int:
String xyValues = "12,13";
String[] xy = xyValues.split(",");
printArray(xy);
int x = int(xy[0]);
int y = int(xy[1]);
println("integer values: " + x + " , " + y);
So, in theory, you should be able to do something like this on Arduino:
int x,y;
void setup() {
//initialize serial
Serial.begin(115200);
}
void loop() {
//simulating the x,y values from the touch screen,
//be sure to replace with the actual readings from
//NOTE! If the screen returns values above 255, scale them to be from 0 to 255
x = map(analogRead(A0),0,1024,0,255);
y = map(analogRead(A1),0,1024,0,255);
//write the data to serial
Serial.print(x);
Serial.print(",");
Serial.print(y);
Serial.print("\n");
}
then on the Arduino side:
import processing.serial.*;
float x,y;
void setup() {
size(400,400);
//update the serial port index based on your setup
Serial arduino = new Serial(this, Serial.list()[0], 115200);
arduino.bufferUntil('\n');
}
void draw() {
background(0);
ellipse(x,y,10,10);
}
void serialEvent(Serial p) {
//read the string from serial
String rawString = p.readString();
//trim any unwanted empty spaces
rawString = rawString.trim();
try{
//split the string into an array of 2 value (e.g. "0,127" will become ["0","127"]
String[] values = rawString.split(",");
//convert strings to int
int serialX = int(values[0]);
int serialY = int(values[1]);
//map serial values to sketch coordinates if needed
x = map(serialX,0,255,0,width);
y = map(serialY,0,255,0,height);
}catch(Exception e){
println("Error parsing string from Serial:");
e.printStackTrace();
}
}
Note The Arduino code above will probably not solve your problem as it is, you need to integrate your touch sensor code, but hopefully it provides some hints on how you can tackle this.
Sending a String, then parsing it is one approach, but not the most efficient. If you have your x,y values in a 0-255 range, you could send just 2 bytes (each coordinate as a single char) instead of up to 8 bytes, but for now it may be much easier to play with Strings rather than jump into bytes straight away.
This tutorial will help you.
5 minutes and you are able to connect each others!
EDIT:
First of all look the first part of the tutorial ("From Arduino..." "...To processing").
In arduino you have just to send your coordinates in your Serial.
Serial.println(coordX);
Serial.println(coordY);
In processing you receive this coordinates as Text but you are able to convert it in Float with parseFloat() function.
This is the code you need in Processing to receive your coordinates and store them in variables.
import processing.serial.*;
Serial myPort; // Create object from Serial class
String val; // Data received from the serial port
float x = 0;
float y = 0;
boolean first = true;
setup() {
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() {
if ( myPort.available() > 0) { // If data is available,
val = myPort.readStringUntil('\n'); // read it and store it in val
if (first) {
x = parseFloat(val);
first = false;
println("x= "+val); //print it out in the console
}
else {
y = parseFloat(val);
first = true;
println("y= "+val); //print it out in the console
}
}
I hope this will help you solve your problem.
I am doing some simple arduino projects in an effort to learn some of the basics.
For this project I am trying to print a line sent through the serial monitor. When I print the line, my leading text prints along with the first character of the user input, and then a new line starts and the leading text prints again along with the rest of the user data. I'm not sure why this is happening.
Here is my code:
char data[30];
void setup()
{
Serial.begin(9600);
}
void loop()
{
if (Serial.available())
{
//reset the data array
for( int i = 0; i < sizeof(data); ++i )
{
data[i] = (char)0;
}
int count = 0;
//collect the message
while (Serial.available())
{
char character = Serial.read();
data[count] = character;
count++;
}
//Report the received message
Serial.print("Command received: ");
Serial.println(data);
delay(1000);
}
}
When I upload the code to my Arduino Uno, and open the serial monitor, I can type in a string like: "Test Message"
When I hit enter, I get the following result:
Command received: T
Command received: est Message
When what I was expecting was:
Command received: Test Message
Can someone point me in the right direction?
Thanks in advance for the help.
Serial.available() doesn't return a boolean it returns how many bytes are in the Arduino's serial buffer. Because you are moving that buffer into a list of 30 chars you should check that the serial buffer is 30 chars long with the condition Serial.available() > 30.
This could be causing the code to execute once as soon as the serial buffer has any data, hence it running for the first letter then again realising more has been written to the buffer.
I'd recommend also completely removing your data buffer and using the data direct from the serial's buffer. e.g
Serial.print("Command received: ");
while (Serial.available()) {
Serial.print((char)Serial.read());
}
Edit: How to wait until serial data finishes being sent
if (Serial.available() > 0) { // Serial has started sending
int lastsize = Serial.available(); // Make a note of the size
do {
lastsize = Serial.available(); // Make a note again so we know if it has changed
delay(100); // Give the sender chance to send more
} while (Serial.available() != lastsize) // Has more been received?
}
// Serial has stopped sending