bluetooth low energy slow reaction time - arduino

I am currently trying to use an Adafruit Feather 32u4 to control a 2 motors (a small remote control car) with an android app. Here's what I am using:
MitAppInventor 2 for the app, obviously the Arduino IDE for the car.
App Inventor doesn't have a pleasant way of sharing the code, but basically I get passed the pairing, and get to where its just the buttons to press. They work perfectly, making the car go forwards and backwards, left and right. The problem I have is when I unplug the feather from the computer, the time between button presses and motors moving goes to about 1.5 seconds which is definitely not okay for driving.
All the Arduino does is take in the array from the phone, which will be Status, 0, 1, 2, 3, or 4. Depending on that number it turns the motors on in the desired direction.
The code I used it just modified code from this guide
This is my Arduino IDE code:
/*********************************************************************
This is an example for our nRF51822 based Bluefruit LE modules
Pick one up today in the adafruit shop!
Adafruit invests time and resources providing this open source code,
please support Adafruit and open-source hardware by purchasing
products from Adafruit!
MIT license, check LICENSE for more information
All text above, and the splash screen below must be included in
any redistribution
*********************************************************************/
#include <Arduino.h>
#include <SPI.h>
#if not defined (_VARIANT_ARDUINO_DUE_X_) && not defined (_VARIANT_ARDUINO_ZERO_)
#include <SoftwareSerial.h>
#endif
#include "Adafruit_BLE.h"
#include "Adafruit_BluefruitLE_SPI.h"
#include "Adafruit_BluefruitLE_UART.h"
#include "BluefruitConfig.h"
/*=========================================================================
APPLICATION SETTINGS
FACTORYRESET_ENABLE Perform a factory reset when running this sketch
Enabling this will put your Bluefruit LE module
in a 'known good' state and clear any config
data set in previous sketches or projects, so
running this at least once is a good idea.
When deploying your project, however, you will
want to disable factory reset by setting this
value to 0. If you are making changes to your
Bluefruit LE device via AT commands, and those
changes aren't persisting across resets, this
is the reason why. Factory reset will erase
the non-volatile memory where config data is
stored, setting it back to factory default
values.
Some sketches that require you to bond to a
central device (HID mouse, keyboard, etc.)
won't work at all with this feature enabled
since the factory reset will clear all of the
bonding data stored on the chip, meaning the
central device won't be able to reconnect.
MINIMUM_FIRMWARE_VERSION Minimum firmware version to have some new features
MODE_LED_BEHAVIOUR LED activity, valid options are
"DISABLE" or "MODE" or "BLEUART" or
"HWUART" or "SPI" or "MANUAL"
-----------------------------------------------------------------------*/
#define FACTORYRESET_ENABLE 1
#define MINIMUM_FIRMWARE_VERSION "0.6.6"
#define MODE_LED_BEHAVIOUR "MODE"
/*=========================================================================*/
// Pin Configuration and Firmware Declarations
#define LED_PIN 13
const unsigned long
BLINKTIME = 100;
unsigned long
t_blink = 0L;
int
blinkState = LOW;
// Create the bluefruit object, either software serial...uncomment these lines
/*
SoftwareSerial bluefruitSS = SoftwareSerial(BLUEFRUIT_SWUART_TXD_PIN, BLUEFRUIT_SWUART_RXD_PIN);
Adafruit_BluefruitLE_UART ble(bluefruitSS, BLUEFRUIT_UART_MODE_PIN,
BLUEFRUIT_UART_CTS_PIN, BLUEFRUIT_UART_RTS_PIN);
*/
/* ...or hardware serial, which does not need the RTS/CTS pins. Uncomment this line */
// Adafruit_BluefruitLE_UART ble(Serial1, BLUEFRUIT_UART_MODE_PIN);
/* ...hardware SPI, using SCK/MOSI/MISO hardware SPI pins and then user selected CS/IRQ/RST */
Adafruit_BluefruitLE_SPI ble(BLUEFRUIT_SPI_CS, BLUEFRUIT_SPI_IRQ, BLUEFRUIT_SPI_RST);
/* ...software SPI, using SCK/MOSI/MISO user-defined SPI pins and then user selected CS/IRQ/RST */
//Adafruit_BluefruitLE_SPI ble(BLUEFRUIT_SPI_SCK, BLUEFRUIT_SPI_MISO,
// BLUEFRUIT_SPI_MOSI, BLUEFRUIT_SPI_CS,
// BLUEFRUIT_SPI_IRQ, BLUEFRUIT_SPI_RST);
// A small helper
void error(const __FlashStringHelper*err) {
Serial.println(err);
while (1);
}
/**************************************************************************/
/*!
#brief Sets up the HW an the BLE module (this function is called
automatically on startup)
*/
/**************************************************************************/
void setup(void)
{
pinMode(LED_PIN, OUTPUT);
while (!Serial); // required for Flora & Micro
delay(500);
Serial.begin(115600);
Serial.println(F("Adafruit Bluefruit Command Mode Example"));
Serial.println(F("---------------------------------------"));
/* Initialise the module */
Serial.print(F("Initialising the Bluefruit LE module: "));
if ( !ble.begin() )
{
error(F("Couldn't find Bluefruit, make sure it's in CoMmanD mode & check wiring?"));
}
Serial.println( F("OK!") );
if ( FACTORYRESET_ENABLE )
{
/* Perform a factory reset to make sure everything is in a known state */
Serial.println(F("Performing a factory reset: "));
if ( ! ble.factoryReset() ){
error(F("Couldn't factory reset"));
}
}
/* Disable command echo from Bluefruit */
ble.echo(false);
Serial.println("Requesting Bluefruit info:");
/* Print Bluefruit information */
ble.info();
Serial.println(F("Please use Adafruit Bluefruit LE app to connect in UART mode"));
Serial.println(F("Then Enter characters to send to Bluefruit"));
Serial.println();
ble.verbose(false); // debug info is a little annoying after this point!
/* Wait for connection */
while (! ble.isConnected()) {
delay(500);
}
// LED Activity command is only supported from 0.6.6
if ( ble.isVersionAtLeast(MINIMUM_FIRMWARE_VERSION) )
{
// Change Mode LED Activity
Serial.println(F("******************************"));
Serial.println(F("Change LED activity to " MODE_LED_BEHAVIOUR));
ble.sendCommandCheckOK("AT+HWModeLED=" MODE_LED_BEHAVIOUR);
Serial.println(F("******************************"));
}
}
/**************************************************************************/
/*!
#brief Constantly poll for new command or response data
*/
/**************************************************************************/
void loop(void)
{
// Now Check for incoming characters from Bluefruit
ble.println("AT+BLEUARTRX");
ble.readline();
ble.waitForOK();
String BLEbuffer = ble.buffer;
if (BLEbuffer.length() && BLEbuffer.indexOf("OK") == -1)
Serial.print(F("[Recv] ")); Serial.println(BLEbuffer);
if (BLEbuffer.indexOf("Status") >= 0) {
Serial.println(F("Status Request Received"));
ble.print("AT+BLEUARTTX=");
if (t_blink) {
ble.println("BLNK");
}
else {
if (blinkState)
ble.println("ON");
else
ble.println("OFF");
}
// check response stastus
if (! ble.waitForOK() ) {
Serial.println(F("Failed to get response"));
}
ble.println("AT+BLEUARTRX");
}
else if (BLEbuffer.indexOf("0") >= 0) {
blinkState = LOW;
digitalWrite(LED_PIN, blinkState);
analogWrite(13, 0);
analogWrite(11, 0);
digitalWrite(18, LOW);
digitalWrite(19, LOW);
digitalWrite(20, LOW);
digitalWrite(21, LOW);
t_blink = 0;
ble.print("AT+BLEUARTTX=");
ble.println("OFF");
//Serial.println(F("OFF Request Received"));
ble.println("AT+BLEUARTRX");
}
else if (BLEbuffer.indexOf("1") >= 0) {
//if (!t_blink) t_blink = millis();
analogWrite(13, 100);
analogWrite(11, 100);
digitalWrite(18, HIGH);
digitalWrite(19, LOW);
digitalWrite(20, LOW);
digitalWrite(21, HIGH);
ble.print("AT+BLEUARTTX=");
ble.println("FORWARD");
//Serial.println(F("BLINK Request Received"));
ble.println("AT+BLEUARTRX");
}
else if (BLEbuffer.indexOf("2") >= 0) {
blinkState = HIGH;
digitalWrite(LED_PIN, blinkState);
analogWrite(13, 100);
analogWrite(11, 100);
digitalWrite(18, LOW);
digitalWrite(19, HIGH);
digitalWrite(20, HIGH);
digitalWrite(21, LOW);
t_blink = 0;
ble.print("AT+BLEUARTTX=");
ble.println("BACK");
//Serial.println(F("ON Request Received"));
ble.println("AT+BLEUARTRX");
}
else if (BLEbuffer.indexOf("3") >= 0) {
analogWrite(13, 100);
analogWrite(11, 100);
digitalWrite(18, HIGH);
digitalWrite(19, LOW);
digitalWrite(20, HIGH);
digitalWrite(21, LOW);
ble.print("AT+BLEUARTTX=");
ble.println("LEFT");
//Serial.println(F("BLINK Request Received"));
ble.println("AT+BLEUARTRX");
}
else if (BLEbuffer.indexOf("4") >= 0) {
//if (!t_blink) t_blink = millis();
analogWrite(13, 100);
analogWrite(11, 100);
digitalWrite(18, LOW);
digitalWrite(19, HIGH);
digitalWrite(20, LOW);
digitalWrite(21, HIGH);
ble.print("AT+BLEUARTTX=");
ble.println("RIGHT");
//Serial.println(F("BLINK Request Received"));
ble.println("AT+BLEUARTRX");
}
BLEbuffer = "";
}
All this should be doing every loop is reading in a line, picking out the character, and running the code block for that character. I don't see a reason for it to be lagging as the amount of data seems to be very minimal. Also there is little to no lag if I have it plugged in and the Serial Monitor running. As soon as I unplug it, it stays connected and everything still works except for the massive delay.
My initial thoughts were that the buffer was getting too full of "blank" commands, and that it had to process all of them before the real commands, but if that was the case then it would be lagging with the serial monitor open.
So far I have tried changing the BAUD rate to a lower number, thinking 300 was the minimum and if the problem was that the stack was getting too many commands to sort through 300 would be a tiny amount compared to the 115600 I had it at before, but this yielded no results. I have also tried cutting back the code and this seems to be the very minimum code I could use to make it still work.
I did read that it might help to apply the onSerialEvent() method, but when I try it gets stuck at:
if ( ble.isVersionAtLeast(MINIMUM_FIRMWARE_VERSION) )
{
// Change Mode LED Activity
Serial.println(F("******************************"));
Serial.println(F("Change LED activity to " MODE_LED_BEHAVIOUR));
ble.sendCommandCheckOK("AT+HWModeLED=" MODE_LED_BEHAVIOUR);
Serial.println(F("******************************"));
}
Could it be that maybe its the wiring? For example, I might need a capacitor before the motors to keep them from having to "ramp up" to the power needed to actually start moving? I'm not super knowledgeable in electrical things but this was just a thought.

So the solution is very simple and I don't think it is a BLE only solution as it only has to do with the Serial commands (I.E. serial.print()). Having these commands in the code after the device is no longer connected to a computer will cause the board to not respond to them or take an extra long time trying to process them before eventually giving up (my guess as to what actually happens).
The solution is to simply comment out all the Serial commands before you upload to the device with intent to run the code without being plugged in. Or you can obviously just erase them all but it might hinder your debugging experience the next time you are trying to edit the code.
I figured instead of deleting the question, answering it with what I found out might help someone else in the future.

Related

rs 485 communication problem between 2 Arduinos

I am a novice to Arduino. I came across an article on rs 485 and currently trying to implement the same between 2 arduino unos. I copied code from internet which is pretty simple but I am unable to make communication work properly. Here is the code for master arduino with explanation of what I am trying to do.
**Master Arduino Code**
/* master will send a message I1LF where I shows start of master message by master.
* 1 shows the slave device No. from whom data is to be fetched and L
* shows that master wants to read slave's sensor data
* and F indicates finish of message by master.
* slave will respond by sending Serial.println(i1) where i is slave no and 1 is to let master know that
* correct slave is sending data. then slave would send sensor_value and then f indicates end of slave message.
* master will display data read from rs 485 bus.
*/
#include<LiquidCrystal.h> //Library for LCD display
//function
LiquidCrystal lcd(4, 5, 6, 7, 8, 9);
const int Enable = 2;
int value1=0;
void setup()
{
Serial.begin(9600);
pinMode(Enable, OUTPUT);
digitalWrite(Enable, HIGH); // put master arduino into transmission mode.
lcd.begin(16,2);
lcd.clear();
}
void loop()
{
Serial.print('I'); // I indicates master has started communication.
Serial.print('1'); // this is the address of slave from whom data is to be fetched.
Serial.print('L'); // this means master wants to read sensor data.
Serial.print('F'); // this means end of message.
Serial.flush(); // wiat untill all data has been pushed to the serial.
digitalWrite(Enable, LOW); // put master into receiving mode.
if(Serial.find('i')) // i will be sent (to indicate start of slave
//message , by the slave that was prompted by
//master.
{
int slave = Serial.parseInt(); // check which slave is sending
//data.
value1 = Serial.parseInt();
if(Serial.read() == 'f' && slave == 1) // f indicates end of message
//sent by slave and 1 is the
//address of the slave sent by
// the slave so that master can
//recognize which slave is this.
{
lcd.setCursor(0,0);
lcd.print("Slave : ");
lcd.setCursor(11,0);
lcd.print(value1);
}
}
digitalWrite(Enable, HIGH);
delay(300);
}
This is the slave arduino code
#include<LiquidCrystal.h>
LiquidCrystal lcd(4, 5, 6, 7, 8, 9);
const int Enable = 2;
const int SlaveNumber = 1;
void setup()
{
Serial.begin(9600);
pinMode(Enable, OUTPUT);
digitalWrite(Enable, LOW); // initially put slave in receiving mode
pinMode(A0, INPUT);
lcd.begin(16,2);
lcd.clear();
}
void loop()
{
if(Serial.available())
{
if(Serial.read()=='I') // all slaves will detect I on rs 485 bus which //means master has started commmunication.
{
int Slave = Serial.parseInt(); // read next character on rs 485 bus
//which would definitely be a digit
//indicating slave no to whom master
//wishes to communicate.
if(Slave == SlaveNumber) // check if master wants to commnucate
//with you.
{
char command = Serial.read(); // read next character in
//serial buffer which would be
//command L
delay(100);
if(command == 'L')
{
if(Serial.read()=='F') // if master's message has
//finished.
{
int AnalogValue = analogRead(0); // read sensor
digitalWrite(Enable, HIGH); // put slave in
//transmission mode.
Serial.print("i"); // i indicates start of
//slave message
Serial.println(SlaveNumber); // send slave no so that
//master can identify which
//slave he is receiving
//data from.
Serial.print(AnalogValue);
Serial.print("f"); // indicates end of message by the
//slave.
Serial.flush();
digitalWrite(Enable, LOW); // put slave in
//listening ( receivig ) mode
}
}
}
}
}
}
This is screen shot of proteous simulation showing Master unable to read slave1's sensor data
enter image description here
I assessed that problem arose because of master and slave both being in transmission mode so I attached a not gate between master's enable pin and slave's enable pin and then master is working fine. but practically attaching a not gate wont be possible. that's why I want to know how to ensure that enable of both master and slave is not high simultaneously. I have tried a couple of strategies and introduced delays at different locations in the code but nothing seems to work. by hit and trial it starts to work sometimes but I want to know the correct way of doing so.
This is screen shot of proteous simulation which shows master reading correctly slave1 data only after I attach a not gate between master Enable pin and Slave's Enable pin.
Code for both master and slave and circuit is exactly the same as before. only a not gate has been used between master's enable pin and slave's enable pin.
enter image description here
I tried another library madleech/Auto485 but that i also showing the same problem. have tried a couple of times adding delays at different locations in master code but to no use. i know problem is because of enable pins of both MAX 485 modules connected to 2 arduinos going high simultaneously but i am unable to figure out how to address this issue.
You need to wait for each byte to be available before reading the serial port.
In your code:
if(Serial.available()) // you wait
{
if(Serial.read()=='I') // all slaves will detect I on rs 485 bus which //means master has started commmunication.
{
// parseInt() does wait for a byte to be availeble, so that works...
int Slave = Serial.parseInt();bus
if(Slave == SlaveNumber)
{
// Here serial.read() will most likely return -1, since it is very
// unlikely that a byte is already available at this point.
char command = Serial.read();
// ...
You should wait for the serial port to have received bytes before reading them.
You can try inserting a loop before calling read(), as in:
while (!Serial.available()) {} // wait for something to read
char byteRead = Serial.read();
This blocking code should help fix the code as you have it now. You should probably explore non-blocking ways of reading serial commands, such as using some sort of finite state machine algorithm. As a rule of thumb, embedded software should avoid blocking.

How do I get rid of the symbols behind my LoRa message reception?

A bit of context, I am participating in the UK CanSat competition. I am sorting out the communication between the CanSat and the ground station. We are using LoRa transceivers as required per the competition. We are using a raspberry pi pico as a emitter and an Arduino nano in the ground station as a receiver.
The LoRa module we are using is this one.
Long story short, when I receive the message in the ground station, there are multiple symbols, here is a picture:
Here is the code for the Arduino (receiver):
// Arduino9x_RX
// -*- mode: C++ -*-
// Example sketch showing how to create a simple messaging client (receiver)
// with the RH_RF95 class. RH_RF95 class does not provide for addressing or
// reliability, so you should only use RH_RF95 if you do not need the higher
// level messaging abilities.
// It is designed to work with the other example Arduino9x_TX
#include <SPI.h>
#include <RH_RF95.h>
#define RFM95_CS 10
#define RFM95_RST 9
#define RFM95_INT 2
// Change to .0 or other frequency, must match RX's freq!
#define RF95_FREQ 433.0
// Singleton instance of the radio driver
RH_RF95 rf95(RFM95_CS, RFM95_INT);
// Blinky on receipt
#define LED 13
void setup() {
pinMode(LED, OUTPUT);
pinMode(RFM95_RST, OUTPUT);
digitalWrite(RFM95_RST, HIGH);
while (!Serial);
Serial.begin(9600);
delay(100);
Serial.println("Arduino LoRa RX Test!");
// manual reset
digitalWrite(RFM95_RST, LOW);
delay(10);
digitalWrite(RFM95_RST, HIGH);
delay(10);
while (!rf95.init()) {
Serial.println("LoRa radio init failed");
while (1);
}
Serial.println("LoRa radio init OK!");
// Defaults after init are 434.0MHz, modulation GFSK_Rb250Fd250, +13dbM
if (!rf95.setFrequency(RF95_FREQ)) {
Serial.println("setFrequency failed");
while (1);
}
Serial.print("Set Freq to: "); Serial.println(RF95_FREQ);
// Defaults after init are 434.0MHz, 13dBm, Bw = 125 kHz, Cr = 4/5, Sf = 128chips/symbol, CRC on
// The default transmitter power is 13dBm, using PA_BOOST.
// If you are using RFM95/96/97/98 modules which uses the PA_BOOST transmitter pin, then
// you can set transmitter powers from 5 to 23 dBm:
rf95.setTxPower(23, false);
}
void loop() {
if (rf95.available()) {
// Should be a message for us now
uint8_t buf[RH_RF95_MAX_MESSAGE_LEN];
//char buf = (char*)buf;
uint8_t len = sizeof(buf);
if (rf95.recv(buf, &len)) {
digitalWrite(LED, HIGH);
Serial.print("Got: ");
Serial.println((char*)buf);
Serial.print("RSSI: ");
Serial.println(rf95.lastRssi(), DEC);
} else {
return;
}
}
}
Disclaimer this code was extracted from the internet.
And here is the code for the Raspberry pi pico (emitter):
import board
import busio
import time
import digitalio
import adafruit_rfm9x
import adafruit_bmp280
"Led configuration"
# Led amarillo
ledambar = digitalio.DigitalInOut(board.GP16)
ledambar.direction = digitalio.Direction.OUTPUT
# Led azul
ledazul = digitalio.DigitalInOut(board.GP17)
ledazul.direction = digitalio.Direction.OUTPUT
"LoRa"
# LoRa radio setup
spi = busio.SPI(clock=board.GP2, MOSI=board.GP3, MISO=board.GP4)
cs = digitalio.DigitalInOut(board.GP6)
reset = digitalio.DigitalInOut(board.GP7)
rfm9x = adafruit_rfm9x.RFM9x(spi, cs, reset, 433.0)
print("RFM9x radio ready")
"Not LoRa from here"
"BMP280 Sensor"
# BMP280 comunication start up
i2c = busio.I2C(scl=board.GP15, sda=board.GP14)
bmp280_sensor = adafruit_bmp280.Adafruit_BMP280_I2C(i2c, address=0x76)
# BMP280 sensor readings
def read_temperature():
return bmp280_sensor.temperature
def read_pressure():
return bmp280_sensor.pressure
while True:
ledazul.value = True
"LoRa"
rfm9x.send("Hello World, this is a test, why does this not work? im going mad!!!!")
print("Radio mensage sent")
"Not LoRa from here"
ledazul.value = False
cansat_temperature = read_temperature()
print("TEMPERATURE:")
print(cansat_temperature)
cansat_pressure = read_pressure()
print("PRESSURE:")
print(cansat_pressure)
print(" ")
time.sleep(2.5)
Disclaimer, this code is designed to do more things than just LoRa communication. The LoRa part of the code is below the tag: "LoRa".
If you have any recommendations on how to improve my code in any way, just let me know, it would be really helpful.
Thank you.
I have tried soldering the antennas, changing them, modifying the code, both in the pico and the Arduino, also tried changing the antennas but nothing worked.
You have a buffer over-read - a major security flaw, same as the infamous Heartbleed bug.
When you pass a char * to Serial.println, it will print the data until it finds a null character. Your python string does not contain such null termination, so the the print function keeps going through the memory until it finds one. You were lucky that it found one quite quickly. It could also go on much longer, depending on what is in the memory at that time.
A naive way to fix the issue would be to just append a null character to the python string:
rfm9x.send("Hello World, this is a test, why does this not work? im going mad!!!!\0")
However, if you were to receive partial data (or someone forgot to add a null character), the issue would reappear.
The proper way to fix the problem is to check how much data is received and only print that much. According to the documentation, the received number of octets is stored in the len parameter. Therefore, you can add null-termination on the receiving end like so:
uint8_t buf[RH_RF95_MAX_MESSAGE_LEN];
// Leave space for null-termination
uint8_t len = sizeof(buf) - 1;
if (rf95.recv(buf, &len))
{
// Add null-termination at the end of the received data.
buf[len] = '\0';
// Print as before.
digitalWrite(LED, HIGH);
Serial.print("Got: ");
Serial.println((char*)buf);
Serial.print("RSSI: ");
Serial.println(rf95.lastRssi(), DEC);
}

cannot turn on relay indefinitely on an arduino

I want to make a device like Knocki(https://knocki.com), which essentially is a relay control using a vibration sensor. i can detect vibrations rn but the problem is, once i knock the relay blinks on and then turns off. i understand this is a lack of programming that is causing this. could someone help me write code which makes it so that when i knock the relay is turned on indefinitely; until I knock again to turn relay off.
And yes u can probably tell that this code is copied from somewhere(https://wiki.keyestudio.com/Ks0068_keyestudio_37_in_1_Sensor_Kit_for_Arduino_Starters#Project_21:_Vibration_Sensor).I took it from the home page of the vibration sensor. the code was initially so that every time i knocked, the onboard Arduino led lit up. Also, right now the relay is blinking faintly every time i knock(Although correctly,in sync with my knocks)
#define SensorLED 13
#define SensorINPUT 3 //Connect the sensor to digital Pin 3 which is Interrupts 1.
unsigned char state = 0;
int Relay = 5;
void setup()
{
pinMode(SensorLED, OUTPUT);
pinMode(SensorINPUT, INPUT);
attachInterrupt(1, blink, FALLING);// Trigger the blink function when the falling edge is detected
}
void loop()
{ if(state!=0)
{
state = 0;
digitalWrite(SensorLED,HIGH);
delay(500);
digitalWrite(Relay,HIGH);
}
else
digitalWrite(SensorLED,LOW);
digitalWrite(Relay,lOW);
}
void blink()//Interrupts function
{ state++;
Yes its in your code: The (bad) example works only because there is a
digitalWrite(SensorLED,HIGH);
->>> delay(500);
a delay for 1/2 sec to keep the led on.So as a check put an other delay after the relay line and it should go on for 1/2 sec too (so the led is lit 1 sec in total)
digitalWrite(SensorLED,HIGH);
delay(500);
digitalWrite(Relay,HIGH);
delay(500);
Thats just for checking -> NEXT STEP:
Get rid of the delays (see blinkwithoutdelay example in
Arduino->File->Examples->2.Digital -> blinkwithoutdelay
and introduce a second state variable e.g.
bool relayStateOn = false;
to get an independent on/off of the relay and the led.(If thats - what I understand -what you want to do)
If you feed your relay from the board, that is not the problem. Please, check the voltage in your relay when you try to set it on, if your voltage falls down, it means that this output to your relay does not supply the necessary current.

How to read switches via serial port C++?

I have an arduino nano. I want to connect MX Cherry switches and detect pressing throught the serial port. What pins should i use on arduino and what code should be uploaded to the plate?
I understand that i have to power the switches so there has to be 5v pin and input pin. But i'm new to electronics so i didn't manage to figure it out.
//that's just basic code for sending a number every second via 13 pin
int i=0;
void setup() {
Serial.begin(57600);
pinMode(13, OUTPUT);
}
void loop() {
i = i + 1;
Serial.println(i);
delay(1000);
}
Basically, i need a way of sending '1' if button is pressed and '0' if it's not.
Perhaps I've misunderstood your question. Why not just read the button and send a '1' if pressed and '0' if not?
void loop(){
int buttonState = digitalRead(buttonPin);
// Assumes active low button
if (buttonState == LOW){
Serial.print('1');
}
else {
Serial.print('0');
}
delay(500);
}
Of course you probably want to add some sort of timing to that so it doesn't send thousands of 0's and 1's per second. I added a delay, but that might not be the best answer for the application you have (and chose not to share). I've also assumed that your button is wired active-LOW with a pull-up since you didn't share that either.

Arduino ultrasonic distance sensor

I am trying to receive information from my sensor, however my output is just 0 all the time, is there something wrong in my code? Everything hardware related is done well.
loop()
{
long duration, inches, cm;
pinMode(pingPin, OUTPUT);
digitalWrite(pingPin, LOW);
delayMicroseconds(2);
digitalWrite(pingPin, HIGH);
delayMicroseconds(5);
digitalWrite(pingPin, LOW);
pinMode(pingPin, INPUT);
duration = pulseIn(pingPin, HIGH);
inches = microsecondsToInches(duration);
cm = microsecondsToCentimeters(duration);
Serial.print(inches);
Serial.print("in; ");
Serial.print(cm);
Serial.print("cm");
Serial.println();
}
long microsecondsToInches(long microseconds)
{
return microseconds / 74 / 2;
}
long microsecondsToCentimeters(long microseconds)
{
return microseconds / 29 / 2;
}
The sensor you have does not use PWM as a way of sending distance. Rather it uses a serail connection. The issue is that you do NOT have a extra serial hardware on the Arduino.
You could use the arduino's serail port to read the sensors data, but you would not be able to log anything to the screen
The speed at which the serial connection runs is 9600 baud, which is to fast to emulate in software.
I advice you to buy a sensor that uses the standard PWM mode of communication. Doing this will save a several headaches .But I should tell you there is a way. It is using the software serial library. The library will help you use digital pins like they are serail pins.
http://arduino.cc/en/Reference/SoftwareSerial
http://www.suntekstore.com/goods-14002212-3-pin_ultrasonic_sensor_distance_measuring_module.html
http://iw.suntekstore.com/attach.php?id=14002212&img=14002212.doc
You are using code for the Parallax PING, which uses a different protocol from the one you have. Here is a link to the datasheet of your sensor. It outputs through standard serial at 9600bps every 50ms.
After many tries and thanks to the help of John b, this was figured out as the proper answer on how to use this kind of sensor properly, it works exactly as needed, the output being perfectly measured
#include <SoftwareSerial.h>
// TX_PIN is not used by the sensor, since that the it only transmits!
#define PING_RX_PIN 6
#define PING_TX_PIN 7
SoftwareSerial mySerial(PING_RX_PIN, PING_TX_PIN);
long inches = 0, mili = 0;
byte mybuffer[4] = {0};
byte bitpos = 0;
void setup() {
Serial.begin(9600);
mySerial.begin(9600);
}
void loop() {
bitpos = 0;
while (mySerial.available()) {
// the first byte is ALWAYS 0xFF and I'm not using the checksum (last byte)
// if your print the mySerial.read() data as HEX until it is not available, you will get several measures for the distance (FF-XX-XX-XX-FF-YY-YY-YY-FF-...). I think that is some kind of internal buffer, so I'm only considering the first 4 bytes in the sequence (which I hope that are the most recent! :D )
if (bitpos < 4) {
mybuffer[bitpos++] = mySerial.read();
} else break;
}
mySerial.flush(); // discard older values in the next read
mili = mybuffer[1]<<8 | mybuffer[2]; // 0x-- : 0xb3b2 : 0xb1b0 : 0x--
inches = 0.0393700787 * mili;
Serial.print("PING: ");
Serial.print(inches);
Serial.print("in, ");
Serial.print(mili);
Serial.print("mili");
Serial.println();
delay(100);
}

Resources