Not exactly sure where to put this, as I don't know exactly where the problem lies.
I have two Arduino's, one acting as a receiver, and one as a transmitter. The transmitter has two buttons that sends a signal to the receiver that rotates a stepper motor left or right.
This works. But my issue is this:
The transmitter will act as a wireless remote control, and needs to run on a battery. When it get's it's power from my computer using a cable, everything runs smootly, but when I switch over to a battery, everything runs slow (fewer signals are sent per second) and there is a longer delay.
What could be the cause of this? And is there a solution?
Details about the project
The battery is fully charged, and a PKCELL LP785060 3.7V 2500mAh.
- Video of it running on battery: https://youtube.com/shorts/Wmz88E51CG0?feature=share
- Video of it running on power from my mac: https://youtube.com/shorts/rRz72ww99hY?feature=share
Code for transmitter:
#include <SPI.h>
#include <RH_RF95.h>
// Radio: feather32u4
#define RFM95_CS 8
#define RFM95_RST 4
#define RFM95_INT 7
// Radio: Change to 434.0 or other frequency, must match RX's freq!
#define RF95_FREQ 434.0
// Radio: Singleton instance of the radio driver
RH_RF95 rf95(RFM95_CS, RFM95_INT);
// Buttons
#define UP_BUTTON 2
#define DOWN_BUTTON 3
// Battery
#define VBATPIN 9
// Variables
uint8_t down_btn_prev;
uint8_t up_btn_prev;
void setup() {
Serial.begin(115200);
while (!Serial) {
delay(1);
}
delay(100);
Serial.println("Transmitter!");
setupRadio();
setupButtons();
}
/**
Possible logic:
* TRANSCIEVER: Move upon received signal with a specified timeout
* If new command is received before timer, cancel timer and set new timer.
* (The transmitter should then be able to send multiple signals in a row by holding it in, but with a max frequency)
*/
void loop() {
if (digitalRead(UP_BUTTON) == LOW /* && up_btn_prev == HIGH */) {
sendPacket(0);
}
if (digitalRead(DOWN_BUTTON) == LOW /*&& down_btn_prev == HIGH*/) {
sendPacket(1);
}
//down_btn_prev = digitalRead(DOWN_BUTTON);
//up_btn_prev = digitalRead(UP_BUTTON);
}
void setupRadio() {
pinMode(RFM95_RST, OUTPUT);
digitalWrite(RFM95_RST, HIGH);
// manual reset
digitalWrite(RFM95_RST, LOW);
delay(10);
digitalWrite(RFM95_RST, HIGH);
delay(10);
while (!rf95.init()) {
Serial.println("LoRa radio init failed");
Serial.println("Uncomment '#define SERIAL_DEBUG' in RH_RF95.cpp for detailed debug info");
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);
// 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 setupButtons() {
pinMode(DOWN_BUTTON, INPUT);
pinMode(UP_BUTTON, INPUT);
down_btn_prev = digitalRead(DOWN_BUTTON);
up_btn_prev = digitalRead(UP_BUTTON);
}
// 0 = UP, 1 = DOWN
void sendPacket(int direction) {
String batt = String(checkBattery(), 2);// using a float and the decimal places
Serial.print("Sending: ");
Serial.println(direction == 0 ? "UP" : "DOWN");
if (direction == 0) {
String upmessage = "UP ";
upmessage.concat(batt);
delay(10);
upmessage[7] = 0;
rf95.send((uint8_t *)upmessage.c_str(), 7);
// Wait for packet to complete
delay(10);
rf95.waitPacketSent();
} else {
String downmessage = "DOWN ";
downmessage.concat(batt);
downmessage[9] = 0;
delay(10);
rf95.send((uint8_t *)downmessage.c_str(), 9);
// Wait for packet to complete
delay(10);
rf95.waitPacketSent();
}
}
/*
* This routine checks the voltage on the battery (if it exists) and returns that value. Should be in the 3.2-4.2 range depending upon the battery used
This returns the current voltage of the battery on a Feather 32u4.
*/
float checkBattery() {
float measuredvbat = analogRead(VBATPIN);
measuredvbat *= 2; // we divided by 2, so multiply back
measuredvbat *= 3.3; // Multiply by 3.3V, our reference voltage
measuredvbat /= 1024; // convert to voltage
return measuredvbat;
}
Code for receiver:
#include <SPI.h>
#include <RH_RF95.h>
// Radio: feather32u4
#define RFM95_CS 8
#define RFM95_RST 4
#define RFM95_INT 7
// Radio: Change to 434.0 or other frequency, must match RX's freq!
#define RF95_FREQ 434.0
// Radio: Singleton instance of the radio driver
RH_RF95 rf95(RFM95_CS, RFM95_INT);
// Stepper
int dirPin = 10; // Step direction orange
int stepPin = 11; // Step pin
String lastDirection = "DOWN";
bool shouldMove = false;
void setup() {
Serial.begin(115200);
while (!Serial) {
delay(1);
}
delay(100);
Serial.println("Transmitter X!");
setupRadio();
pinMode(stepPin, OUTPUT);
pinMode(dirPin, OUTPUT);
digitalWrite(stepPin, LOW);
digitalWrite(dirPin, LOW);
}
int numberOfLoops = 0;
void loop() {
receiveRadioMessage();
if (shouldMove) {
if (lastDirection == "UP") {
digitalWrite(dirPin, HIGH);
} else {
digitalWrite(dirPin, LOW);
}
digitalWrite(stepPin, HIGH);
delayMicroseconds(900);
digitalWrite(stepPin, LOW);
delayMicroseconds(900);
}
if (numberOfLoops > 0) {
numberOfLoops--;
}
if (numberOfLoops == 0) {
shouldMove = false;
}
}
void setupRadio() {
pinMode(RFM95_RST, OUTPUT);
digitalWrite(RFM95_RST, HIGH);
Serial.println("Feather 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");
Serial.println("Uncomment '#define SERIAL_DEBUG' in RH_RF95.cpp for detailed debug info");
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 receiveRadioMessage() {
if (rf95.available()) {
// Should be a message for us now
uint8_t buf[RH_RF95_MAX_MESSAGE_LEN];
uint8_t len = sizeof(buf);
memset(buf, 0, len);
if (rf95.recv(buf, &len)) {
String received = buf;
Serial.print("Got: ");
Serial.println(received);
if(received.indexOf("UP") >= 0) {
shouldMove = true;
lastDirection = "UP";
numberOfLoops = 300;
}
if(received.indexOf("DOWN") >= 0) {
shouldMove = true;
lastDirection = "DOWN";
numberOfLoops = 300;
}
}
else {
Serial.println("Receive failed");
}
}
}
/**
Possible logic:
* Move upon received signal with a specified timeout
* If new command is received before timer, cancel timer and set new timer.
* (The transmitter should then be able to send multiple signals in a row by holding it in, but with a max frequency)
*/