nRF52840 is ignoring certain setWriteCallback() calls - bluetooth-lowenergy

so I just started experimenting with the Adafruit Feather nRF52840 board and have set up a working BLE connection between the board and another device.
Usually, everything works fine by sending data from the other device to the nRF52840, but sometimes, if I send 2 packets at the exact same time, the setWriteCallback is only registering one of them.
Is there a way I can work around this issue?
This is how I set up my callback in code:
void charact_write_callback(uint16_t conn_hdl, BLECharacteristic* chr, uint8_t *data, uint16_t len)
{
if(data[0] == 2){
Serial.print(data[1] == 0 ? "Left" : "Right");
Serial.println(" Hand Touch occured");
}
}
When both hands are actually touching and sending data to the device, this callback only receives one.
Thanks in advance and Greetings

Related

How do I control servos using Processing code and an Arduino UNO Board?

To the stackoverflow community,
First, let me begin by saying that I'm not a code writer (though I'm quite familiar with LabVIEW). My background is in Laser and optical system design and development. Currently, I'm trying to integrate servos into an optical component used in a long range atmosphere mapping Lidar. The optical component, refereed to as a TR-Swich, is critical in maintaining the alignment between the Transmitted Laser pulse stream and back-scattered Return light. In order to ensure long-term alignment and compensate for optical mount thermal and shock drift, the servos - connected to optical mount pitch and yaw actuators - will allow our customers to adjust the TR-Swich as needed and thereby maintain optimum signal returns. Due to a variety of constraints (time, space, ease of integration into existing hardware, etc.), I'm hoping to use servos, which are small and reliable and can be easily controlled using an Arduino UNO board. I've already proven that they work quite well to move and set the position of the actuators; now I'm trying to get the GUI interface working...which hopefully is where all of you come in...
Since I'm new to Arduino board code (and the related Processing code), I snooped around and found code published on hackster.io (back in 2020) - which is close to what I'm looking for. The code was written by engineerkid (his hackster user name). I copied his code for both the Arduino board and the Processing GUI, but haven't been able to get it to work. I reached out to him (through hackster) but haven't received a reply. The message I sent him was, " Hi Enginnerkid, First, I want to thank you for posting the example! It's very close to what I ultimately need for adjusting optical mounts using servos. I copied your code for both the Arduino and Processing sketches and it's close to working, but something isn't quite right. The servo (practically identical to what you're using in your example) moves to the center position and the display based on the mouse position using the Processing code work just fine. Unfortunately, the servo doesn't respond to the mouse movements. As a heads up, currently I'm only using one servo - are two servos required in order for the code to work? Going on this premise, I deleted the code related to one of the servos, but still wasn't able to achieve any movement. I did some browsing regarding communication problems between Arduino and Processing code and found the following comment (which might be relevant), " The serial monitor in Arduino is like a separate terminal program so it and your Processing sketch are competing for the same serial connection to the Arduino." Any help you can provide would be greatly appreciated! Thanks! Steve"
His Arduino code is:
#include <Servo.h>
char tiltChannel=0, panChannel=1;
Servo servoTilt, servoPan;
char serialChar=0;
void setup()
{
servoTilt.attach(9); //The Tilt servo is attached to pin 9.
servoPan.attach(10); //The Pan servo is attached to pin 10.
servoTilt.write(90); //Initially put the servos both
servoPan.write(90); //at 90 degress.
Serial.begin(57600); //Set up a serial connection for 57600 bps.
}
void loop()
{
while(Serial.available() <=0); //Wait for a character on the serial port.
serialChar = Serial.read(); //Copy the character from the serial port to the variable
if(serialChar == tiltChannel){ //Check to see if the character is the servo ID for the tilt servo
while(Serial.available() <=0); //Wait for the second command byte from the serial port.
servoTilt.write(Serial.read()); //Set the tilt servo position to the value of the second command byte received on the serial port
}
else if(serialChar == panChannel){ //Check to see if the initial serial character was the servo ID for the pan servo.
while(Serial.available() <= 0); //Wait for the second command byte from the serial port.
servoPan.write(Serial.read()); //Set the pan servo position to the value of the second command byte received from the serial port.
}
//If the character is not the pan or tilt servo ID, it is ignored.
}
His Processing code is:
import processing.serial.*;
Serial port; // The serial port we will be using
int xpos=90; // set x servo's value to mid point (0-180)
int ypos=90; // set y servo's value to mid point (0-180)
void setup()
{
size(360, 360);
frameRate(100);
String arduinoPort = Serial.list()[0];
port = new Serial(this, arduinoPort, 57600);
}
void draw()
{
fill(175);
rect(0,0,360,360);
fill(255,0,0); //rgb value so RED
rect(180, 175, mouseX-180, 10); //xpos, ypos, width, height
fill(0,255,0); // and GREEN
rect(175, 180, 10, mouseY-180);
update(mouseX, mouseY);
}
void update(int x, int y)
{
//Calculate servo postion from mouseX
xpos= x/2;
ypos = y/2;
//Output the servo position ( from 0 to 180)
port.write(xpos+"x");
port.write(ypos+"y");
}
If you would like to look at his code, and the really cool example he set up, the site link is:
https://www.hackster.io/engineerkid/servo-motor-control-using-arduino-and-processing-af8225#team
As mentioned above, I simplified the code by removing the pan servo control, but still wasn't able to get any response from the servo using the tilt portion of the code. It does appear to be related to a communication bottleneck, I'm just not sure what small snip-it of code needs to be added to prevent the conflict. By the way, one indication that the communication is at fault is the LED serial com lights on the Arduino board. Prior to using (or trying to use the Processing GUI) I copied published code for moving a servo just with the Arduino code and was able to position the servo at any desired angle (form 0 to 180 degrees). I noticed that with each upload of the code (which would set the servo to any chosen hard coded angle value), the LEDs would flicker and toggle back and forth as the new code uploaded. Now with the GUI, only 1 LED stays on continuously... which is probably not a good sign...
As I mentioned to Engineerkid, any help you can provide would be greatly appreciated!
Thanks for your time.
Steve
The java code does not send what your arduino sketch expects (or vice versa)
You're reading a single control character and compare it with one of two allowed values:
serialChar = Serial.read();
if(serialChar == tiltChannel){
I suggest to change at the Arduino side
char tiltChannel='x', panChannel='y';
And to modify the java side to
port.write("x");
port.write(xpos);
Same for the other servo, too.
And make sure each java port.write sends a single byte only.

Sim800L lag/delay before incoming calls are visible to arduino

I use SIM800L GSM module to detect incoming calls and generally it works fine. The only problem is that sometimes it takes up to 8 RINGS before the GSM module tells arduino that someone is calling (before RING appears on the serial connection). It looks like a GSM Network congestion but I do not have such issues with normal calls (I mean calls between people). It happens to often - so it cannot be network/Provider overload. Does anybody else had such a problem?
ISP/Provider: Plus GSM in Poland
I don't put any code, because the problem is in different layer I think
sorry that I didn't answer earlier. I've tested it and it turned out that in bare minimum code it worked OK! I mean, I can see 'RING' on the serial monitor immediately after dialing the number. So it's not a hardware issue!
//bare minimum code:
void loop() {
if(serialSIM800.available()){
Serial.write(serialSIM800.read());
}
if(Serial.available()){
serialSIM800.write(Serial.read());
}
}
In my real code I need to compare calling number with the trusted list. To do that I saved all trusted numbers in the contact list on the sim card (with the common prefix name 'mytrusted'). So, in the main loop there's if statement:
while(mySerial.available()){
incomingByte = mySerial.read();
inputString += incomingByte;
}
if (inputString.indexOf("mytrusted") > 0){
isTrusted = 1;
Serial.println("A TRUSTED NUMBER IS CALLING");
}
After adding this "if condition" Arduino sometimes recognize trusted number after 1'st call, and sometimes after 4'th or 5'th. I'm not suspecting the if statement itself , but the preceding while loop, where incoming bytes are combined into one string.
Any ideas, what can be improved in this simply code?
It seems, I found workaround for my problem. I just send a simple 'AT' command every 20 seconds to SIM800L (it replies with 'OK' ). I use timer to count this 20 seconds interval (instead of simply delay function)
TimerObject *timer2 = new TimerObject(20000); //AT command interval
....
timer2->setOnTimer(&SendATCMD);
....
void SendATCMD () {
mySerial.println("AT");
timer2->Stop();
timer2->Start();
}
With this simple modification Arduino always sees incoming call immediately (after 1 ring)

Arduino Serial.read doesn't work

My Arduino Mega (with CH340 but all the drivers needed installed) has stopped reading from the serial port. Doesn´t matter what I write it keeps saving number 50. I have tried with simple examples codes as this one:
int incomingByte = 0; // for incoming serial data
void setup() {
Serial.begin(9600); // opens serial port, sets data rate to 9600 bps
}
void loop() {
// send data only when you receive data:
if (Serial.available() > 0) {
// read the incoming byte:
incomingByte = Serial.read();
// say what you got:
Serial.print("I received: ");
Serial.println(incomingByte, DEC);
}
}
And I get the same response.
The arduino has been working fine untill today. Serial.print() works also fine, it's just Serial.read() Anyone knows what the problem could be?? I haven't found much help on the internet, seems I am the first one dealing with this issue.
Okay, so I found what my problem was. Don't know if it was Serial.read or Serial println / Serial.write, some of these functions were converting from integers to chars, so numbers appeared to be only between 49 and 58. Using Serial.print instead it works perfectly. Thanks for the answers by the way.

Two xbee beacons drowning each other out?

I'm trying to create a pair of arduino/xbee beacons that will transmit some information (ultimately GPS coordinates) to each other at all times. The problem is that when they're both on, neither one seems to receive. I'm guessing it's because both might be transmitting at the same time and drowning the others message out. However, I'm not sure of a better approach since neither one is a slave or master. Here's my setup:
Hardware:
A pair of XBee-Pro 900 XSC S3B xbees.
A pair of teensy (arduino compatible with multiple UARTs)
XBee Setup
VID: 542D
DT: 8153
Serial connected to Serial 3 on Teensy
Code
long lastTxTime = 0
void setup() {
Serial.begin(9600);
Serial3.begin(9600);
}
void loop() {
long now = millis();
// Send ever 0.5 seconds
if (now - lastTxTime > 500) {
Serial.println("SEND!");
Serial3.println("WOOT!");
lastTxTime = now;
}
delay(100);
// Print anything received
while(Serial3.available()) {
char c = Serial3.read();
Serial.print(c);
}
}
When I connect both Teensy's to separate terminals, both of them output "SEND" and rarely receive a "WOOT". I put one of the XBees straight on a USB board to a terminal and it output most of the "WOOT" messages from the other.
What can I do to make this work?
What you need to look into is flow control. In the wireless standard, they use RTS (Request to Send) & CTS (Clear to Send). The RTS/CTS pins on Xbee might be what you need,

Arduino: serial.read within ISR

I am writing a small test program that attempts to perform a serial.write() followed by a serial.read() within an ISR. The code will eventually be used to prompt an external GSM shield to send an SMS on a regular basis.
ISR(TIMER2_OVF_vect) {
Serial.println("AT+CMGS=\"0123456789\""); // Tell Sim900 To prepare sms to number 01...
while(Serial.read()!='>'); // Wait for Sim900 to respond
Serial.print("A text message"); // the SMS body
Serial.write(0x1A); //Confirm send instruction
Serial.write(0x0D);
Serial.write(0x0A);
}
}
What I have found after a lot of testing is that Serial.read() within an ISR is not capable of reading a live serial prompt, instead it will only read any input that was buffered before the ISR was triggered.
Is there any way around this?
The only solution I have found is to place this code instead within the main loop(). But I want to send the SMS using a timer interrupt.
Thank you
You need to place the code in the loop() but using an IF:
float toBeSent = interval;
loop() {
if (millis() > toBeSent) {
Send();
toBeSent = milli() + interval;
}
}
interval is your sending interval in milliseconds.
I had a similar problem a while ago which I managed to resolve by using the Arduino SoftwareSerial library instead of the hardware based Serial.read.
There are some overheads associated with using SoftwareSerial, and you can only read one port at a time, so I leave it up to those with a better understanding of the Arduino platform to tell you if this is a good idea, but one of the benefits of this library is that you can use it within an ISR.
To use the SoftwareSerial library, add the following two lines of code at the top of your sketch remembering to replqce the rx_pin and tx_pin with the corresponding pin values you want to use:
#include <SoftwareSerial.h>
SoftwareSerial mySerial(rx_pin, tx_pin);
Then replace the key word Serial throughout your sketch with mySerial (or whatever name you have chosen to give your SoftwareSerial instance).
An important thing to keep in mind when using SoftwareSerial is that you can only use certain pins on the Arduino so read the documentation first.
If you wanted to live dangerously you could enable interrupts inside the ISR and use a flag to prevent reentry.
int flag=0;
ISR(TIMER2_OVF_vect) {
flag = 1
if (flag){return;}
sei();
Serial.println("AT+CMGS=\"0123456789\""); // Tell Sim900 To prepare sms to number 01...
while(Serial.read()!='>'); // Wait for Sim900 to respond
Serial.print("A text message"); // the SMS body
Serial.write(0x1A); //Confirm send instruction
Serial.write(0x0D);
Serial.write(0x0A);
}
flag = 0;
}

Resources