Send Battery Level from my Bluefruit Feather ESP32 through BLE - arduino

I am using this demo from official docs from Bluefruit Feather BLE, so I have added inside the loop of my Arduino IDE as follows:
float measuredvbat = analogRead(VBATPIN); // #define VBATPIN A9
measuredvbat *= 2; // we divided by 2, so multiply back
measuredvbat *= 3.3; // Multiply by 3.3V, our reference voltage
measuredvbat /= 1024; // convert to voltage
Serial.print("VBat: " ); Serial.println(measuredvbat);
I am getting values and I'd like to send the values over BLE but I think I should do it with another thread, because I have more code reading other received values, but I do not know the best way to do it. Thanks in advance!!

Finally I have figured out how to read it. I comment the issue in this official thread

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.

Protocol for writing data to 16x2 LCD via I2C

I am new to electronics and has completed a tutorial on how to operate a 16x2 Character LCD via I2C in Arduino using liquidCrystal_I2C. Everything works fine but I have a question about the low level interaction between the I2C and the LCD. Looking at the library's source code, I notice that when writing a 4 bits nibble (LiquidCrystal_I2C::write4bits), the code writes the nibble to the I2C expander first
(LiquidCrystal_I2C::expanderWrite), and then writes again when pulsing the Enable bit. Why is the first expanderWrite necessary? Why can't write4bits just call pulseEnable (with the blacklight bit set)?
I am sure there is a reason as I checked other library like RPLCD and see a similar pattern. Can anyone enlighten me? Thank you.
From the datasheet I found the LCD requires specific timing in the communication protocol.
On the rising edge of the enable line the Register Select and Read/Write lines must have already settled for tsu1 (100ns). On the falling edge of the enable line the data must have already settled for tsu2 (60ns). By writing _data they are also writing the RS and R/W lines as they are the lower nibble of _data.
This article covers the topic very thoroughly.
//**** From LiquidCrystal_I2C.h
// flags for backlight control
#define LCD_BACKLIGHT 0x08
#define LCD_NOBACKLIGHT 0x00
#define En B00000100 // Enable bit
#define Rw B00000010 // Read/Write bit
#define Rs B00000001 // Register select bit
// ^--------Backlight bit defined above
// ^^^^---------Data bits
//**** From LiquidCrystal_I2C.cpp
void LiquidCrystal_I2C::write4bits(uint8_t value) {
expanderWrite(value);
pulseEnable(value);
}
void LiquidCrystal_I2C::expanderWrite(uint8_t _data){
Wire.beginTransmission(_addr);
Wire.write((int)(_data) | _backlightval);
Wire.endTransmission();
}
void LiquidCrystal_I2C::pulseEnable(uint8_t _data){
expanderWrite(_data | En); // En high
delayMicroseconds(1); // enable pulse must be >450ns
expanderWrite(_data & ~En); // En low
delayMicroseconds(50); // commands need > 37us to settle
}

Arduino as slave with multiple i2c addresses

I would like to use an Arduino as an i2c slave. But I require that the Arduino acts as multiple devices by registering itself with multiple i2c addresses.
This is probably not something one would normally do, but here is my reason for doing it:
I want to use an Arduino to act as Telemetry sensors for Spektrum Telemetry. The Telemetry receiver has a few i2c plugs which connects to multiple sensors (current 0x02, voltage 0x03, airspeed 0x11, etc) each that have a fixed i2c address which the Telemetry receiver expects.
I would like to use one Arduino to act as all these devices by registering itself with all of the above addresses, and responding appropriately with the readings.
I could use one Arduino per sensor, which seems silly as I can perform all these readings with one Arduino pro-mini.
I know you can register the Arduino using
Wire.begin(0x02);
But I require something similar to this (pseudo code)
Wire.begin(0x02, 0x03, 0x11);
And when a request is received, I need to know with what address the Arduino was queried.
For example (pseudo code)
void receiveEvent(byte address, int bytesReceived){
if(address == 0x02){
// Current reading
}
else if(address == 0x03){
// Voltage reading
}
else if(address == 0x11){
// Airspeed reading
}
}
Any advice would be appreciated.
It is not possible to make the Arduino listen to to multiple slave addresses by using the Wire library since Wire.begin() only allows to pass a single slave address.
Even the Atmel ATmega microcontroller on which most Arduinos are based only allows its hardware 2-wire serial interface (TWI) to be set to a single 7-bit address via its 2-wire address register TWAR. However, it is possible to work around this limitation by masking one or more address bits using the TWI address mask register TWAMR as documented (somewhat briefly) in e.g. this ATmega datasheet section 22.9.6:
The TWAMR can be loaded with a 7-bit Salve (sic!) Address mask. Each of the bits in TWAMR can mask (disable) the corresponding address bits in the TWI address Register (TWAR). If the mask bit is set to one then the address match logic ignores the compare between the incoming address bit and the corresponding bit in TWAR.
So we would first have to set up the mask bits based on all I2C addresses we want to respond to by OR'ing them and shifting right to match the TWAMR register layout (TWAMR holds mask in bit7:1, bit0 is unused):
TWAMR = (sensor1_addr | sensor2_addr | sensor3_addr) << 1;
The main problem from here on will be to find out which particular I2C address was queried (we only know it was one that matches the address mask).
If I interpret section 22.5.3 correctly, stating
The TWDR contains the address or data bytes to be transmitted, or the address or data bytes received.
we should be able to retrieve the unmasked I2C address from the TWDR register.
ATmega TWI operation is interrupt-based, more specifically, it utilizes a single interrupt vector for a plethora of different TWI events indicated by status codes in the TWSR status register.
In the TWI interrupt service routine, we'll have to
make sure the reason why we've entered the ISR is because we've been queried. This can be done by checking TWSR for status code 0xA8 (own SLA+R has been received)
decide which sensor data to send back to the master based on what I2C address was actually queried by checking the last byte on the bus in TWDR.
This part of the ISR could look something like this (untested):
if (TWSR == 0xA8) { // read request has been received
byte i2c_addr = TWDR >> 1; // retrieve address from last byte on the bus
switch (i2c_addr) {
case sensor1_addr:
// send sensor 1 reading
break;
case sensor2_addr:
// send sensor 2 reading
break;
case sensor3_addr:
// send sensor 3 reading
break;
default:
// I2C address does not match any of our sensors', ignore.
break;
}
}
Thanks for asking this interesting question!
I really do like vega8's answer, but I'd also like to mention that if your I2C master isn't going to clock things incredibly fast, using a software-based implementation of I2C would also be feasible and give you the freedom you want.
You might want to consider that approach if rough calculation shows that the time spent in the TWI ISR is too high and interrupts might start to overlap.
void setup()
{
Wire.begin(0x11 | 0x12); // Adr 11 and 12 are used for Alt and Speed by Spectrum DX
Wire.onRequest(requestEvent); // register callback function
TWAMR = (0x11 | 0x12) << 1; // set filter for given adr
}
void requestEvent() {
int adr = TWDR >> 1; // move 1 bit to align I2C adr
if (adr == 0x12) // check for altitude request at adr 12
Wire.write(tmpSpektrumDataAlt, 16); // send buffer
if (adr == 0x11) // check for speed request at adr 11
Wire.write(tmpSpektrumDataSpd, 16); // send buffer
}
This works with a Spectrum DX8 with telemetry module.
The Spectrum interface was made public on Sectrums home page. Technical documents.
There could be other devices on the I2C bus, the TWAMR should be set with as less bits as possible. So I think the better way to calculate the mask is:
AddrOr = Addr1 | Addr2 | Addr3 | Addr4 ...
AddrAnd = Addr1 & Addr2 & Addr3 & Addr4 ...
TWAMR = (AddrOr ^ AddrAnd) << 1
while TWAR can be set as either AddrOr or AddrAnd
In this way we can limit the possibility of address conflict to the minimum

Arduino RF24 library Delay after write function causes no byte availability

It's about the RF24 library you can find here. http://maniacbug.github.io/RF24/index.html
I transmit data from one Arduino to another using NRF24L01 radios.
When I use the write-function on the transmitter arduino (joystick is an array) and after that I put in a delay higher then 10, the available function returns false.
Transmitter
radio.write( joystick, sizeof(joystick) );
delay(20);
Receiver
if(!available())
print('No data'); // delay > 10 --> No data will be printed
Why is it working with a delay of 10 but not above? Has it something to do with timeouts which is mentioned in the docs of the library?: http://maniacbug.github.io/RF24/classRF24.html#a4cd4c198a47704db20b6b5cf0731cd58
Thank you for your answers.

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