I don't know exactly this is the correct place to post this question , but my problem involves both external interrupt mechanism as well as softwareserial.
Suppose , I have initialised two random digital pins , say(8 and 9, rx, tx respectively) and intend to use the softwareserial library to communicate with another arduino. But my arduino is asleep(idle mode ). If I join pins 2 and 8 , will a serial message received at 8 be able to trigger an interrupt and wake up my arduino?
If I want to maximise power saving , what are the various things I can safely disable, so that this mechanism still works?
You don't have to connect the the reception pin to the interrupt pin. SoftwareSerial uses the PCI (pin change interrupt) and that one is able to wake an Arduino in "power down" sleep mode. Why don't you use the hardware serial interface instead of SoftwareSerial?
Why don't you use the hardware serial interface instead of SoftwareSerial?
+1
...but if you really need a second serial port, and you're using pins 8 & 9, use AltSoftSerial instead of SoftwareSerial. AltSoftSerial is the best software serial library, because it is very efficient. SoftwareSerial is very inefficient, because it disables interrupts for loooong periods of time. This will interfere with other parts of your sketch or with other libraries.
pylon:
You don't have to connect the the reception pin to the interrupt pin. SoftwareSerial uses the PCI (pin change interrupt) and that one is able to wake an Arduino in "power down" sleep mode. Why don't you use the hardware serial interface instead of SoftwareSerial?
I tried it out , but things do not seem to be working . Please help me out . I have posted the codes for both the arduinos .
Connections: pin 11 of one arduino connected to pin 12 of other arduino and vice versa.
//Sleeping arduino
#include <avr/sleep.h>
#include <SoftwareSerial.h>
#define RXpin 11
SoftwareSerial mySerial(11,12);
volatile boolean triggered=false;
void sleepNow(){
set_sleep_mode(SLEEP_MODE_PWR_DOWN);
sleep_mode();
}
ISR (PCINT3_vect){
triggered=true;
}
void setup() {
// put your setup code here, to run once:
mySerial.begin(28800);
Serial.begin(9600);
digitalWrite(RXpin,LOW);
//pin change interrupt
PCMSK0 |=bit(PCINT3);
PCIFR |=bit(PCIF0);
PCICR |=bit(PCIE0);
}
void loop() {
// put your main code here, to run repeatedly:
if(triggered==true){
triggered=false;
Serial.println("Woken!");
delay(500);
if(mySerial.available()){
int data=mySerial.parseInt();
Serial.println(data);
}
else{
Serial.println("Sleeping Now");
delay(500);
sleepNow();
}
}
//Code for sender
#include <SoftwareSerial.h>
SoftwareSerial mySerial(11,12);
int otp=1;
void setup() {
// put your setup code here, to run once:
mySerial.begin(28800);
}
void loop() {
// put your main code here, to run repeatedly:
if(otp==1){
otp=0;
char otwp='W';
mySerial.write(otwp);
delay(90);
int data=42;
mySerial.write(data);
}
}
Learn to use code tags, I don't read code without code tags!
Connections: pin 11 of one arduino connected to pin 12 of other arduino and vice versa.
You should connect GNDs too. Are these the only connections you have? Post a wiring diagram (can be a drawing by hand)!
Here is the wiring diagram and the code!
//Sleeping arduino
#include <avr/sleep.h>
#include <SoftwareSerial.h>
#define RXpin 11
SoftwareSerial mySerial(11,12);
volatile boolean triggered=false;
void sleepNow(){
set_sleep_mode(SLEEP_MODE_PWR_DOWN);
sleep_mode();
}
ISR (PCINT3_vect){
triggered=true;
}
void setup() {
// put your setup code here, to run once:
mySerial.begin(28800);
Serial.begin(9600);
digitalWrite(RXpin,LOW);
//pin change interrupt
PCMSK0 |=bit(PCINT3);
PCIFR |=bit(PCIF0);
PCICR |=bit(PCIE0);
}
void loop() {
// put your main code here, to run repeatedly:
if(triggered==true){
triggered=false;
Serial.println("Woken!");
delay(500);
if(mySerial.available()){
int data=mySerial.parseInt();
Serial.println(data);
}
else{
Serial.println("Sleeping Now");
delay(500);
sleepNow();
}
}
//Code for sender
#include <SoftwareSerial.h>
SoftwareSerial mySerial(11,12);
int otp=1;
void setup() {
// put your setup code here, to run once:
mySerial.begin(28800);
}
void loop() {
// put your main code here, to run repeatedly:
if(otp==1){
otp=0;
char otwp='W';
mySerial.write(otwp);
delay(90);
int data=42;
mySerial.write(data);
}
}
I am having problems in uploading the pic. The wiring is straightforward. Pin11 of one arduino is connected to pin 12 of other arduino. Pin 12 of first arduino connected to pin11 of second arduino . Their grounds are also connected together.
I am still waiting for a reply!!!!!!!!!!!!!!!!!!
I tried it out , but things do not seem to be working
What did you try out? What exactly does not work?
mySerial.begin(28800);
In my experience SoftwareSerial does not reliably work with baud rates higher than 9600, even if the Arduino does nothing else.
ISR (PCINT3_vect){
triggered=true;
}
Why do you use the PCI yourself if you want to use SoftwareSerial? Don't touch that, the library enables the interrupt and it should get the interrupts and not your placeholder code.
So , should I get rid of the ISR ? But what about the variable "triggered"? Where to incorporate it? How shall I know that the arduino has woken?
As you can see , this variable is very important in this program!
Guys, finally got it to work, the pin change interrupt wakes up the arduino , but I am having problems with some print statements thereafter.
//Sleeping arduino
#include <avr/sleep.h>
#include <SoftwareSerial.h>
SoftwareSerial mySerial(11,12);
volatile boolean triggered=false;
void sleepNow(){
set_sleep_mode(SLEEP_MODE_PWR_DOWN);
sleep_mode();
triggered=true;
}
void setup() {
// put your setup code here, to run once:
mySerial.begin(9600);
Serial.begin(9600);
}
void loop() {
// put your main code here, to run repeatedly:
if(triggered==true){
triggered=false;
delay(500);
Serial.println("Woken!");
char c='w'; //#1
mySerial.write(c); //#2
delay(200); //#3
byte data=mySerial.read();
Serial.println(data);
}
else{
Serial.println("Sleeping Now");
delay(500);
sleepNow();
}
}
//Sender code
#include <SoftwareSerial.h>
SoftwareSerial mySerial(11,12);
int otp=1;
void setup() {
// put your setup code here, to run once:
mySerial.begin(9600);
Serial.begin(9600);
}
void loop() {
char otwp;
// put your main code here, to run repeatedly:
if (otp == 1) {
if (mySerial.available()) {
otwp = mySerial.read();
Serial.println(otwp);
}
else {
otwp = 'W';
mySerial.write(otwp);
}
if (otwp == 'w') {
otp = 0;
byte data = 42;
mySerial.write(data);
}
delay(100);
}
}
The sender arduino sends 'W ' to master arduino , PCI on pin 11 is triggered and it wakes up.
However , the problem is :
The serial.println statements do not seem to work all the time. For example , if I comment out lines
#1,#2,#3 in first code , "Woken" is printed , but it vanishes if I include these three lines.
But I am sure that it wakes up because the sender arduino receives a 'w'.What is going wrong? The integer value is also not getting printed.
So , should I get rid of the ISR ? But what about the variable "triggered"? Where to incorporate it? How shall I know that the arduino has woken?
Simply because it wakes up from doing nothing. You could change your code this way if you really need that variable:
Serial.println("Sleeping Now");
delay(500);
sleepNow();
triggered = true;
As you can see , this variable is very important in this program!
Sorry, I cannot see that. You don't need it and if you use the PCINT that way SoftwareSerial will not work correctly. It probably sends out the stuff you want but the reception will not work.
So, what should I do to ensure that both transmission and reception work properly?
As I already wrote: Remove that PCINT handling code and let SoftwareSerial do that work.
BTW, you still didn't tell us why you use that crippled piece of code (SoftwareSerial).
I have already removed the PCInt , plz check the last piece of code I had uploaded.The problem still persists.
I can only guess what exactly the problem in your case is. My guess is some strange interaction of the blocking SoftwareSerial with the serial interface.
I don't understand what your code should do and you don't describe exactly what it really does. I would try to lower the complexity of the two components until you get the sleep/wake-up correctly done. Then you can add the additional functionality one feature after the other.
I still don't understand why you use that awful SoftwareSerial. You get much more problems with it than you might think.
I have found what the problem in this case was . Actually , I had hooked both arduinos onto my laptop and was switching ports continuously . That is why , I was missing the messages on the serial , because , by the time , I could switch ports and turn on the serial for the sleeping arduino , it had already gone through the whole process and also gone back to sleep. Works just fine on different laptops.
However, one small problem. How do I read a single integer from the serial if my serial has been receiving a lot of messages like characters and integers( only one integer and many characters are received). It seems that the serial does an addition of the ascii values of the characters as well.
I don't understand your problem, please explain in greater detail.
Suppose , at different times , my arduino is receiving different messages over software serial eg, characters and finally it receives an integer . I want to access only the integer . So , I declare an int variable and do a standard serial.read or serial.parseInt , but what happens is that , I get perhaps the sum of ascii values of the characters +the number as output.
For debugging , I commented out everything except the first character receive command and the final serial.read command. My first character received was 'W'. The integer I get , is the ascii value of W, i.e. 87.
The serial.flush command has also got its function redefined . What to do? I found an answer on forum, it said , end serial after every transmission or reception and then turm it back on , but this is causing problems, as I may miss out on data during the switching. Aren't there are better methods for getting rid of all previous communications without turning serial off momentarily?
On a serial line you need to establish a protocol that defines what the different bytes transfered mean. There are several methods how to design such a protocol but beginners should use an ASCII based protocol. That way you can use the parseInt method. Define the separation characters you need, for example a space to separate the fields and a newline to separate messages. That way you can throw away all characters until you reach the first newline. From now on read all the fields you defined and the message should end in a newline again (which you should check).
I hope I gave you enough input to design your own protocol.