radio control with arduino - arduino

Hi I am attempting to read from an rc transmitter using an Arduino Uno board, I have a signal pin connected from the receiver to pin 9 on the Arduino. Here is the code I would really appreciate some help all I am trying to achieve is the read the pmw from the receiver. I am able to plug a servo into the receiver and that works fine along with a motor I am just struggling when I try and use the Arduino with the receiver. When I run my program all I get in the Serial monitor are values such as 9991,9972,10030,10050 that are completely unrelated.
I want to have a pmw value that I can map to 0-255 in order to control a motor
My Circuit:
battery -> ESC(for BEC to regulate five volts back to receiver)-> receiver -> ch3 signal pin -> Arduino uno (pin9)
void setup() {
Serial.begin(9600);
}
void loop() {
int pwm = pulseIn(9, HIGH, 25000);
Serial.println(pwm);
delay (5);
}

You are using pulseIn which returns a time (in ms). The time being how long it waited for a HIGH signal. If you want the actual value, use analogRead. You can still use pulseIn, just don't use the return value
void setup() {
Serial.begin(9600);
}
void loop() {
byte pwm = analogRead(A5) / 4;
Serial.println(pwm);
delay(5);
}

Related

SPI Arduino Interface with Absolute Encoder

I am trying to retrieve data from an RLS absolute rotary encoder via SPI through Arduino Uno. I have managed to learn the basics of SPI, but I can't seem to get this working. I keep printing the transfer data and keep getting 255.
I also use the recommended pins for Arduino Uno here: https://www.arduino.cc/en/reference/SPI
Here is the link to the Absolute Encoder DataSheet: https://resources.renishaw.com/en/details/data-sheet-orbis-true-absolute-rotary-encoder--97180
Any help is appreciated.
Here is my code I have been trying:
#include <SPI.h>
unsigned int data;
int CS = 10; //Slave Select Pin
// The SS pin starts communication when pulled low and stops when high
void setup() {
Serial.begin(9600);
RTC_init();
}
int RTC_init() {
pinMode(CS, OUTPUT);
SPI.begin();
SPI.setBitOrder(LSBFIRST); // Sets Bit order according to data sheet (LSBFIRST)
SPI.setDataMode(SPI_MODE2); // 2 or 3, Not sure (I have tried both)
digitalWrite(CS, LOW); // Start communications
/*
Commands List:
Command "1" (0x31) – position request (total: 3 bytes) + 4 for multi-turn
Command "3" (0x33) – short position request (total: 2 bytes) + 4 for multi-turn
Command "d" (0x64) – position request + detailed status (total: 4 bytes) + 4 for multi-turn
Command "t" (0x74) – position request + temperature (total: 5 bytes) + 4 for multi-turn
Command "v" (0x76) – serial number (total: 7 bytes)
*/
unsigned int data = SPI.transfer(0x33); // Data
digitalWrite(CS, HIGH); // End communications
return(data);
}
void loop() {
Serial.println(RTC_init());
}
First, you forgot to set your CS pin to output. That won't help.
void setup()
{
Serial.begin(9600);
digitalWrite(CS, HIGH); // set CS pin HIGH
pinMode(CS, OUTPUT); // then enable output.
}
SPI is a two way master/slave synchronous link, with the clock being driven by bytes being sent out by the master. This means that when transacting on SPI, you are expected to send out as many bytes as you want to receive.
As shown on the timing diagram on page 14 of the datasheet, you are expected to send one byte with the command, then as many null bytes as the response requires minus 1.
The diagram shows the clock being low at idle, and input bits being stable when the clock goes low, that's SPI mode 1.
To read the position, for a non-multiturn encoder.
unsigned int readEncoderPos()
{
// this initialization could be moved to setup(), if you do not use
// the SPI to communicate with another peripheral.
// Setting speed to 1MHz, but the encoder can probably do better
// than that. When having communication issues, start slow, then set
// final speed when everything works.
SPI.beginTransaction(SPISettings(1'000'000, MSBFIRST, SPI_MODE1));
digitalWrite(CS, LOW);
// wait at least 2.5us, as per datasheet.
delayMicroseconds(3);
unsigned int reading = SPI.transfer16(0x3300); // 0x3300, since we're sending MSB first.
digitalWrite(CS, HIGH);
// not needed if you moved SPI.beginTransaction() to setup.
SPI.endTransaction();
// shift out the 2 status bits
return reading >> 2;
}

How to read XBee RSSI in API mode?

I am trying to test a XBee RSSI in API mode at receiving end, how can I retrieve the RSSI value of the receiving radio in arduino.
I configured both XBee in API-2 mode and are connected to arduino by pin 4-5(rxtx & txrx) to Xbee radios.
Sending frame code is like below and there is no problem in transmission at both ends,
uint8_t data[] = {'H','i'};
XBeeAddress64 addr64 = XBeeAddress64();
addr64.setMsb(0x00000000); // Msb address of receiver
addr64.setLsb(0x00000000); // Lsb address of receiver
ZBTxRequest zbTx = ZBTxRequest(addr64, data, sizeof(data));
xbee.send(zbTx);
delay(1000);
At the receiving end I tried pulseIn of arduino and .getRssi() of , The former function gives "0" in result while the later gives "102" but remains the same as I move the Xbee radios away from each other.
What should I need to do for getting correct RSSI at the receiving end..?
Hopefully this answer helps you and others.
Assuming you are using the following lib:
https://github.com/andrewrapp/xbee-arduino
and you have a series 1 module you can use the following test code for quick diagnostics. the commented parts can of course also be used if needed
#include <XBee.h>
#include <SoftwareSerial.h>
// XBee's DOUT (TX) is connected to pin 8 (Arduino's Software RX)
// XBee's DIN (RX) is connected to pin 9 (Arduino's Software TX)
SoftwareSerial serial1(8, 9); // RX, TX
XBee xbee = XBee();
XBeeResponse response = XBeeResponse();
Rx16Response rx16 = Rx16Response();
Rx64Response rx64 = Rx64Response();
// uint8_t xbeeOption = 0;
// uint8_t xbeeData = 0;
uint8_t xbeeRssi = 0;
void setup() {
Serial.begin(9600);
serial1.begin(9600);
xbee.setSerial(serial1);
}
void loop() {
xbee.readPacket(100);
if (xbee.getResponse().isAvailable()) {
Serial.println("Xbee available");
if (xbee.getResponse().getApiId() == RX_64_RESPONSE || xbee.getResponse().getApiId() == RX_16_RESPONSE) {
Serial.println("64 or 16");
if (xbee.getResponse().getApiId() == RX_16_RESPONSE) {
Serial.println("16");
xbee.getResponse().getRx16Response(rx16);
// xbeeOption = rx16.getOption();
//Serial.print("xbeeOption: "); Serial.println(xbeeOption);
//xbeeData = rx16.getData(0);
//Serial.print("xbeeData: "); Serial.println(xbeeData);
xbeeRssi = rx16.getRssi();
Serial.print("xbeeRssi: "); Serial.println(xbeeRssi);
}
else {
Serial.println("64");
xbee.getResponse().getRx64Response(rx64);
//xbeeOption = rx64.getOption();
//Serial.print("xbeeOption: "); Serial.println(xbeeOption);
//xbeeData = rx64.getData(0);
//Serial.print("xbeeData: "); Serial.println(xbeeData);
xbeeRssi = rx64.getRssi();
Serial.print("xbeeRssi: "); Serial.println(xbeeRssi);
}
}
}
If you use a series2 module there is only the way using the hardware pwm signal: In order for the RSSI pwm signal to be updated it needs to have received an API packet. Also, for the series 2 Xbee this applies only for the last hop of the packet, so from last router to destination. You need to use the XBee rssi pin and some coding depending on your appliance.
The rssi for distance is not very reliable and you will see a change perhaps every 10 to 15 meters while sending packets. So just moving a Xbee around on your workplace will not change the values.
EDIT:
When using a series 2 module there is the following possibility: connect the rssi pin of the xbee (6) to an Arduino pwm pin (eg 10) and measure the incoming signal, which could then be mapped to a quality or/and distance range. So writing your own rssi function. The usual xbee libs only support series1 modules.

How to turn motor counter-clockwise

Currently, my code below turns on the motor, delays for a bit then starts again. This is all being done in the clockwise direction, however how can I write my code so it can turn counter-clockwise?
int motorPin = 3;
void setup()
{
pinMode(motorPin, OUTPUT);
}
void loop()
{
startStopMotor(135);
delay(1000);
startStopMotor(0);
delay(1000);
}
void startStopMotor(int speed){
analogWrite(motorPin, speed);
}
By the code you share i'am guessing you are running a low power 5v dc motor... but you should edit your answer to give us what type of hardware you are using. This is not an answer but an idea of what you should be looking for... Basically on the motor i suppose you have, you have pin 1 and pin 2. Pin 1 is connected to a PWM signal and pin 2 is connected to ground. This configuration allows you to run your motor clock'wise. To run your motor counter clock'wise you need to invert the direction of the current basically have pin 1 connected to ground and pin 2 connected to a PWM signal.
Now there are multiple ways of doing this, i am unsure of the exact code to do this on an arduino but your pin 1 and 2 will be connected each to a PWM pin. In the code you will need to tell the arduino to put Pin 1 or 2 as a pullDown pin which basically mimics a ground thus telling the direction the other pin will output a PWM
this is not example code but it will give you an idea of what it should look like
void loop(){
//move clock'wise
pin1.pullup();
pin2.pulldown();
analogWrite(pin1, 180);
//move counterclock'wise
pin2.pullup();
pin1.pulldown();
analogWrite(pin2, 180);
}

Arduino Mega 2560 Interrupt w/ Rotary Encoder

I started out using the Uno and I was able to get an interrupt working from a rotary library I found online but when I moved the project to the Mega and tried changing it for the different pins it stops. I spent a few hours trying to figure out the interrupt pin on the mega from online sources and just can't find any good resource to explain the mega interrupt pins sufficiently.
I am trying to use interrupts like so.
Rotary r = Rotary(10,11);
void setup(){
PCICR |= (1 << PCIE0);
PCMSK0 |= (1 << PCINT4) | (1 << PCINT5);
sei();
}
ISR(PCINT0_vect){
//stuff
}
It doesnt really matter what pin I am using for the interrupt if someone has a preferred method. I just need it to work.
Arduino interrupts are described here. It is easier to use than the example code you provide.
//Mega2560
// external interrupt int.0 int.1 int.2 int.3 int.4 int.5
// pin 2 3 21 20 19 18
void setup()
{
// interrupt # 0, pin 2
attachInterrupt(0, myISR, CHANGE); // Also LOW, RISING, FALLING
}
void loop()
{
}
void myISR() // must return void and take no arguments
{
// stuff
}
You don't need to enable interrupts with sei();, because attachInterrupt() does it for you. But you can disable interrupts with cli(); and re-enable them with sei();

Arduino UNO analogRead always returns 1023

So my problem is as title says: Arduino UNO analogRead always returns 1023.
But when I burn the same sketch in Arduino Mega 2650 everything works like a charm.
I have tried to change Atmel chips on the UNO, have tried like 3 of them (ATMEGA328P-PU) and nothing changes.
I'm trying to count signals from a hall effect sensor and display the count on a 7 segment display.
Here is the code:
#include "SevSeg.h"
SevSeg sevseg;
volatile int rpmcount;
void setup() {
Serial.begin(9600);
pinMode(2,INPUT_PULLUP);
rpmcount = 0;
sevseg.Begin(1,3,4,5,6,7,8,9,10,11,12,13);
}
int border=15;
void loop() {
int tmp=0;
tmp = analogRead(0);
if(!digitalRead(2))rpmcount=0;
Serial.println(tmp,DEC);
if(tmp<=border && res >border){
rpmcount++;
if(rpmcount>9999)rpmcount=0;
}
res=tmp;
sevseg.NewNum(rpmcount,(byte) 0);
sevseg.PrintOutput();
}
Any help would be much appreciated
This sounds to me as if you had the internal pullup resistor on the ADC pin enabled.
generic checklist:
ACD bit in ACSR is 0 (comparator enable)
MUX bits in ADMUX set properly
correct AREF selected
ADC pin set as input
internal pull up resistors are deselected

Resources