Arduino publish/subscribe to PubNub - android

I am trying to create an IoT based smart house system. It contains of my android application which sends and receives messages from/to PubNub (subscribes and publishes on certain channels) and Arduino UNO board with some LEDs and movement sensor (PIR). My android app seems to be working fine, it sends and receives messages, but the problem is with Arduino. In the beginning it receives messages from PubNub but after couple (exactly 2) publishes it stops receiving messages, it can just publish. Here is my arduino code:
byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED };
char pubkey[] = "<pub key>";
char subkey[] = "<sub key>";
char channel[] = "publish";
char channel1[] = "subscribe";
char uuid[] = "Arduino";
volatile int pirpin = 2;
iotbridge arduino;
void initialize(){
Serial.begin(9600);
Serial.println("Serial set up");
pinMode(6, OUTPUT);
digitalWrite(6, LOW);
pinMode(pirpin, INPUT);
while (!Ethernet.begin(mac)) {
Serial.println("Ethernet setup error");
delay(1000);
}
Serial.println("Ethernet set up");
}
void do_something(String value){
Serial.println("in the callback");
Serial.println(value);
}
void pin_ISR() {
arduino.send(channel1, "\"Movement\"");
digitalWrite(6, HIGH);
delay(50);
}
void setup()
{
initialize();
arduino.init( pubkey, subkey, uuid);
Serial.println("PubNub set up");
attachInterrupt(0, pin_ISR, RISING);
}
void loop()
{
String returnmessage;
Ethernet.maintain();
Serial.println("waiting for a message");
returnmessage = arduino.connect(channel);
// callback function of sorts, to work with the received message
do_something(returnmessage);
Serial.println();
}
I am just testing the receiving and sending messages so it does not contain LED control. It uses interrupt on pin2 and when it becomes HIGH Arduino publishes a message, which should be received by android app. Thank you for your help in advance.

Related

Sending data from Arduino Bluetooth

I want to send some data (int) to android app, I can do it by writing text in Serial, but I need to send int from code. All I get is "?". I'm not sure what type of data SerialBT.write should I use.
Here is my code:
void setup() {
Serial.begin(115200);
SerialBT.begin("ESP32test"); //Bluetooth device name
Serial.println("The device started, now you can pair it with bluetooth!");
}
void loop() {
RawValue = analogRead(15);
Voltage = (RawValue / 4096.0) * 3300; // Gets you mV
Amps = ((Voltage - ACSoffset) / mVperAmp);
OdczytNap= analogRead(2);
napiecie=OdczytNap*(3300/4096.0);
napiecie=map(OdczytNap,0,1023,0,5);
SerialBT.write(napiecie);
SerialBT.write(Amps);
if (SerialBT.available()) {
Serial.write(SerialBT.read());
}
delay(20);
}

Using data received from Arduino via Bluetooth

I am working on an Android app that will constantly receive data from an Arduino HC-05 and store it in a database. For now I am focusing on receiving the data properly (so just displaying it on the screen is my next step).
I have followed this guide (PDF) to setup a basic app that will receive data from the Arduino. However, it doesn't include a section about using the received data. I've tried adding two lines of code to the handleMessage function in order to display the received data on screen, but I don't see any difference in the textview (it stays "Hello World!").
I know that my Arduino is sending the data just fine, since on another app called "Serial Bluetooth Terminal" it is displayed properly. Here is the code for the Handler class:
Handler mHandler = new Handler() {
#Override
public void handleMessage(Message msg) {
byte[] writeBuf = (byte[]) msg.obj;
int begin = (int)msg.arg1;
int end = (int)msg.arg2;
switch(msg.what) {
case 1:
String writeMessage = new String(writeBuf);
writeMessage = writeMessage.substring(begin, end);
// 2 lines of code I've added here:
TextView tempTextView = (TextView) findViewById(R.id.text_view);
tempTextView.setText(writeMessage);
break;
}
}
};
Aside from the 2 lines, the code is basically the same as the final stage of the guide. And here is the code for the Arduino (which currently just sends "1 2.00 3.00" over and over):
#include <SoftwareSerial.h>
SoftwareSerial BTSerial(0, 1); //RX|TX
int Temp= 1;
float Ph = 2;
float Ec = 3;
void setup() {
Serial.begin(9600);
BTSerial.begin(9600);
}
void loop() {
Serial.print(Temp);
Serial.print(" ");
delay(100);
Serial.print(Ph);
Serial.print(" ");
delay(100);
Serial.print(Ec);
Serial.print(" ");
delay(100);
Serial.print('\n');
if(Serial.available())
BTSerial.write(Serial.read());
}

Receive the data without own sent by QUdpSocket

I'm testing a P2P communication by udp with Qt 5.4(on Windows 10 64bit).
On Windows to Windows, this code can get a message("SendFromHost") from an another device. But on Android to Windows, this code got a own sent message("SendFromGuest") and finished the program.
Please tell me how to get a message without own sent.
void Network::start()
{
findLanSocket = new QUdpSocket(this);
connect(findLanSocket, SIGNAL(stateChanged(QAbstractSocket::SocketState)),
this, SLOT(onUdpStateChanged(QAbstractSocket::SocketState)));
findLanSocket->bind(findPort, QUdpSocket::ShareAddress);
QByteArray datagram = "SendFromGuest";
findLanSocket->writeDatagram(datagram.data(), datagram.size(), QHostAddress::Broadcast, findPort);
}
void Network::onUdpStateChanged(QAbstractSocket::SocketState s)
{
if (s == QAbstractSocket::BoundState) {
connect(findLanSocket, SIGNAL(readyRead()), this, SLOT(onReadyUdpRead()));
}
}
void Network::onReadyUdpRead()
{
QByteArray datagram; QHostAddress haddr;
datagram.resize(findLanSocket->pendingDatagramSize());
findLanSocket->readDatagram(datagram.data(), datagram.size(), &haddr);
QString rev = QString::fromUtf8(datagram);
if (rev == "SendFromHost"){
result = haddr.toString();
qDebug() << result;
success();
return;
}
}
A broadcast UDP datagram can also be received by its sender, that's the expected behavior. See How to ignore your own broadcast udp packets for instance.

Problems when sending a continuous stream of data over BLE

I'm wondering if anybody can help me figure out what is causing the data I am sending to become corrupt.
My setup is currently an Arduino pro mini with a HM-10 bluetooth module connected (I have also tried HM-11 Module too) and an Android application to receive the bluetooth data.
Module setup: http://letsmakerobots.com/node/38009
If I send data with big enough intervals then the data is fine, but if I send the data continuously I see messages getting mixed up and lost. To test this I send "$0.1,0.2,0.3,0.4,0.5" to the Android application from the Arduino, sometimes the stream of data appears to send fine but other times it is really quite scrambled. Please see the below graphs that demonstrate this:
Good case:
Bad case:
Arduino code:
String inputString = ""; //Hold the incoming data.
boolean stringComplete = false; //Determines if the string is complete.
boolean realtime = false;
void setup()
{
Serial.begin(9600);
delay(500);
Serial.print("AT+START");
delay(500);
}
void loop()
{
if(stringComplete)
{
if(inputString.equals("rStart"))
{
Serial.println("$startACK");
realtime = true;
}
else if(inputString.equals("stop"))
{
Serial.println("$stopACK");
realtime = false;
}
else{
Serial.print(inputString);
}
inputString = "";
stringComplete = false;
}
if(realtime)
{
Serial.println("$0.1,0.2,0.3,0.4,0.5,0.6");
delay(10);
}
}
void serialEvent() {
while (Serial.available())
{
// get the new byte:
char inChar = (char)Serial.read();
if (inChar == '\n')
{
stringComplete = true;
}
else
{
inputString += inChar;
}
}
}
The Android side just receives the data and then parses it in an IntentService:
#Override
protected void onHandleIntent(Intent intent) {
//Incoming command.
String rawData = intent.getStringExtra(DataProcessingIntentService.REQUEST);
//Append our new data to our data helper.
Log.i(this.getClass().getName(), "Previous Raw: (" + DataProcessingHelper.getInstance().getData() + ")");
DataProcessingHelper.getInstance().appendData(rawData);
Log.i(this.getClass().getName(), "New Raw: (" + DataProcessingHelper.getInstance().getData() + ")");
commandStartIndex = DataProcessingHelper.getInstance().getData().indexOf("$");
commandEndIndex = DataProcessingHelper.getInstance().getData().indexOf("\n");
//Set this as the data starting point.
if(commandStartIndex != -1){
DataProcessingHelper.getInstance().offsetData(commandStartIndex);
}
//Ensure that a command has been found and that the end index is after the starting index.
if(commandStartIndex != -1 && commandEndIndex > commandStartIndex){
//Remove the command structure from the command.
command = DataProcessingHelper.getInstance().getData().substring(commandStartIndex+1, commandEndIndex-1); //Remove the \r\n end command.
DataProcessingHelper.getInstance().offsetData(commandEndIndex+1);
if(command.length() > 1){
//Split the data out of the comand.
splitData = command.split(",");
Log.i(this.getClass().getName(), "Broadcasting the processed data. (" + command + ")");
//Broadcast data.
Intent broadcastIntent = new Intent();
broadcastIntent.setAction(DataProcessingIntentService.RESPONSE);
broadcastIntent.addCategory(Intent.CATEGORY_DEFAULT);
broadcastIntent.putExtra(DataProcessingIntentService.RESPONSE, splitData);
sendBroadcast(broadcastIntent);
}else{
Log.e(this.getClass().getName(), "Command is less than 1 character long!");
}
}
}
Thank you for any help!
I have now figured out what was causing this problem. It appears that BLE only supports a maximum of 20 bytes per a transaction. The time between these transactions is different depending on what you are using. I'm currently using notifications which means that I can send 20 bytes every 7.5 milliseconds maximum. I have opted for 10 milliseconds to be safe. I will now need to look into breaking up packets into 20 bytes maximum to ensure no data corruption.

Receiving data from Arduino to Android Device via USB

I am trying to receive data from Arduino to my Android device. I started from here
In the activity part of the application, they did
#Override
public void onProgressChanged(SeekBar seekBar, int progress,
boolean fromUser) {
if(fromUser){
if(sUsbController != null){
sUsbController.send((byte)(progress&0xFF));
}
}
}
In the send function
public void send(byte data) {
mData = data;
synchronized (sSendLock) {
sSendLock.notify();
}
}
And in the UsbRunnable part
private class UsbRunnable implements Runnable {
private final UsbDevice mDevice;
UsbRunnable(UsbDevice dev) {
mDevice = dev;
}
#Override
public void run() {//here the main USB functionality is implemented
UsbDeviceConnection conn = mUsbManager.openDevice(mDevice);
if (!conn.claimInterface(mDevice.getInterface(1), true)) {
return;
}
// Arduino Serial usb Conv
conn.controlTransfer(0x21, 34, 0, 0, null, 0, 0);
conn.controlTransfer(0x21, 32, 0, 0, new byte[] { (byte) 0x80,
0x25, 0x00, 0x00, 0x00, 0x00, 0x08 }, 7, 0);
...
...
conn.bulkTransfer(epOUT, new byte[] { mData }, 1, 0);
So, App took the progress of the seekbar and sent it to the Arduino.
But, I want my app to receive data from Arduino. I guess I need to use bulktransfer function as well. think that I want to save the data to mData variable.
How can I do that?
Using the bulkTransfer method is the way to go. You will need to use the IN endpoint to receive the data. For instance, to get a byte of data from the Arduino use this:
byte[] reply = new byte[1]; // to store data from Arduino
int size = 1; // receive at most 1 byte of data
int timeout = 100; // try to receive data for up to 100 milliseconds
int count = conn.bulkTransfer(epIN, reply, size, timeout);
if(count < 0) {
Log.d("ArduinoUSB", "Failure occurred when receiving from Arduino");
} else {
Log.d("ArduinoUSB", "Received " + count + " bytes: " + Arrays.toString(reply));
}
The data will be stored in reply.

Categories

Resources