Oh just one more thing. Is "irCode" the name of the variable which holds the Hex codes from the remote?
Correct. I just used that as an example. The name will depend on your code / library.
A serial monitor baud rate not matching the sketch would indeed explain strange characters but these are likely still to be consistent for a specific button on the IR remote control. Anyway, let's see how you get on with it.
I assumed that this line:
nsIrNec::dataOut,HEX
is defined by the input of the remote so I tried doing this:
switch (nsIrNec::dataOut,HEX)
{
case 0xFFA25D:
{
p_pos += 5;
pitch.write(p_pos);
}
case 0xFFE21D:
{
r_pos += 5;
rotate.write(r_pos);
}
}
But I get the warning:
warning: overflow in implicit constant conversion [-Woverflow]
case 0xFFA25D:
^~~~
for both switch cases.
Not really sure what this warning refers to. Do you guys know?
Take the HEX out to leave just
switch (nsIrNec::dataOut )
The HEX is simply for print formatting.
New issue. Running this code:
#include <Servo.h>
#include <AFMotor.h>
#include "IrNec.h"
AF_DCMotor motor(1); // DC motor on M1
AF_DCMotor pump(3); // Pump at M3
Servo pitch; // Pitch of Nozzle at Pin 9
Servo rotate; // Rotating plate for nozzle at Pin 10
int p_pos = 0; // variable to store the pitch position
int r_pos = 0; // variable to store the rotation position
void setup() {
Serial.begin(9600) ;
pitch.attach(9); // attaches the servo on pin 9 to the servo object
rotate.attach(10); // attaches the servo on pin 10 to the servo object
pitch.write(p_pos);
rotate.write(r_pos);
// Set to the pin number of an external interrupt pin and connect the IR receiver to it.
// Uno/Nano etc. : pin2 or pin3
// ATTINY841 : pin1 (PB1)
// ESP8266 : Any GPIO pin apart from GPIO16
// see attachInterrupt() for other examples and more details
nsIrNec::begin(2) ; // MUST BE EXTERNAL INTERRUPT PIN
}
void loop() {
nsIrNec::loop() ; // check for new data
if ( nsIrNec::dataOut != 0 ) {
// print interpreted data then reset it
Serial.println(nsIrNec::dataOut,HEX) ;
Serial.println();
nsIrNec::dataOut = 0 ; //clear
switch (nsIrNec::dataOut)
{
case 0xFFA25D:
{
Serial.println("CH-");
p_pos += 5;
pitch.write(p_pos);
}
case 0xFFE21D:
{
r_pos += 5;
rotate.write(r_pos);
}
}
}
}
I get the right output from the IR remote but no response from my servo motors.
Also the IR receiver doesn't appear to detect all my button presses on the remote. It only detects once in every 3 or so seconds.
Also sorry for putting all my issues here, we're kinda straying from the original topic of this forum now.
Make sure you add
....
break;
at the end of every
case
Also, you are also doing this in the wrong order. You clear nsIrNec::dataOut after you use it, that is as the last statement at the end of the if block. As it is, it will be zero in the switch statement.
Something like:
void loop() {
nsIrNec::loop() ; // check for new data
if ( nsIrNec::dataOut != 0 ) {
// print interpreted data then reset it
Serial.println(nsIrNec::dataOut, HEX) ;
Serial.println();
switch (nsIrNec::dataOut)
{
case 0xFFA25D:
{
Serial.println("CH-");
p_pos += 5;
pitch.write(p_pos);
break ;
}
case 0xFFE21D:
{
r_pos += 5;
rotate.write(r_pos);
break ;
}
}
nsIrNec::dataOut = 0 ; //clear
}
}
Hopefully this is the last issue, the IR receiver doesn't appear to pick up all my button presses. If I repeatedly press one button, it only picks up one like every 10-20 seconds randomly.
But whenever it does pick it up, the servo motor responds.
The NEC protocol has a special repeat sequence. If you hold the key down, if first sends the keypress, then it sends the repeat code 0xFFFFFFFF at intervals of about 120 ms.
If you want some action to continue while the key is pressed you have to treat a code of 0xFFFFFFFF as "continue doing the last valid action". If you do that, the system won't be quite as responsive because, after processing an action, you'll have to wait until the 150 ms has expired, to be certain that you'll have caught any repeat sequence from the remote control.
It is quite easy to do in software, especially if you want to treat all keys in the same way.
You set a timer when the key press is detected and store the pressed key. You refresh the timer when you detect a repeat code. You cancel the old key press when either the timer expires (say after 150 ms) or if a different key press is detected.
Oh sorry I wasn't clear.
I don't get any output from the remote. I get the hex code but then I don't get anything afterwards. I tested to see if I was just pressing too quickly, but even after pausing for a second, it still doesn't register anything consistently. I also tried swapping buttons after waiting; nothing, still no output.
Most odd. If it is the code, then it is almost as if it is not hitting this after processing a key press:
nsIrNec::dataOut = 0 ; //clear
Do you get the same effect when you hit a key which has no effect on the servo ?
Did you have the same effect with the old code which may indicate a problem with the remote control?
The same effect happens with the other buttons and this didn't happen with my old code.
I believe I have located the issue.
pitch.attach(9);
rotate.attach(10);
I commented out this block
pitch.attach(9); // attaches the servo on pin 9 to the servo object
rotate.attach(10); // attaches the servo on pin 10 to the servo object
pitch.write(p_pos);
rotate.write(r_pos);
and the outputs began working as expected. The hex codes were outputted every time I pressed every button.
Any idea why this code could cause this?
You have to now post your complete sketch.
But any blocking code (especially if it suspends interrupts for a protracted period) will interfere with the IR detection function.
Here's my complete code.
#include <Servo.h>
#include <AFMotor.h>
#include "IrNec.h"
AF_DCMotor motor(1); // DC motor on M1
AF_DCMotor pump(3); // Pump at M3
Servo pitch; // Pitch of Nozzle at Pin 9
Servo rotate; // Rotating plate for nozzle at Pin 10
int p_pos = 0; // variable to store the pitch position
int r_pos = 0; // variable to store the rotation position
void setup() {
Serial.begin(9600) ;
pitch.attach(9); // attaches the servo on pin 9 to the servo object
rotate.attach(10); // attaches the servo on pin 10 to the servo object
pitch.write(p_pos);
rotate.write(r_pos);
nsIrNec::begin(2) ; // MUST BE EXTERNAL INTERRUPT PIN
}
void loop() {
nsIrNec::loop() ; // check for new data
if ( nsIrNec::dataOut != 0 ) {
// print interpreted data then reset it
Serial.println(nsIrNec::dataOut,HEX) ;
Serial.println();
switch (nsIrNec::dataOut)
{
case 0xFFA25D:
{
Serial.println("CH-");
p_pos += 20;
pitch.write(p_pos);
break;
}
case 0xFFE21D:
{
r_pos += 5;
rotate.write(50);
break;
}
}
nsIrNec::dataOut = 0; //clear
}
}
This line was just to test if the switch case worked.
rotate.write(50);
I don't know servo.h, but the angle p_pos is likely to exceed 180 degrees at some point.
Post also a link to your motor controller shield.
It is an l293d motor shield
I also soldered a few pins on the bottom right to access A5 and A4 as well as the 5v and ground, and 1 pin for the Digital pin 2.
What is the reason for using both AFMotor.h and Servo.h ?
The sample code which comes with your shield uses just AFMotor.h: https://www.jaycar.com.au/medias/sys_master/images/images/9505700151326/XC4472-manualMain.pdf
Having said that, I don't know these libraries, but the risk is that they conflict with each other in some way.
The AFMotor library does not support Servo motors iirc which is why I also have the Servo library.
I'm not really familiar with Arduino Libraries. Perhaps someone knows other libraries which can control servo motors, dc motors and can receive input from IR remote.
I guess now you are justified in opening a new thread to focus specifically on the issues related to the motors, that is selection of an appropriate library etc.. This thread has been dominated by IR related matters.