I am using an Arduino Uno to read an encoder to determine direction and distance for a Automation Direct Click PLC motor control. I want to pass a value to the Arduino from the PLC. I am able to have the PLC communicate with the Arduino using the short sketch below that continuously reads (Serial.available).
#include <SoftwareSerial.h>
#define RS485_DIR_PIN 4
unsigned char Cmd;
unsigned char Terminate = "$00";
unsigned char i;
float Duct;
SoftwareSerial mySerial(2, 3); // RX, TX
void setup()
{
pinMode(RS485_DIR_PIN, OUTPUT); //Set RS485 direction pin as output
digitalWrite(RS485_DIR_PIN, LOW); //Set RS485 chip as receiver
Serial.begin(9600);
mySerial.begin(9600);
while (!Serial)
{
; // wait for serial port to connect. Needed for Leonardo only
}
digitalWrite(RS485_DIR_PIN, HIGH); //Set RS485 as transmitter
//delay(10);
//MCU send some message to wifi bee throutht software serial
Serial.println("Hello,this is RS232&RS485 Shield testing program.");
}
void loop() // run over and over
{
digitalWrite(RS485_DIR_PIN, LOW); //Set RS485 as receiver
if (Serial.available())
{
float Temp = Serial.parseFloat();
if (Temp != Duct) {
Serial.println(" Temp ");
Serial.println(Temp);
if (Serial.find(Terminate)) {
Duct = Temp;
}// end Serial.find
}// end if(Temp != Duct)
digitalWrite(RS485_DIR_PIN, HIGH);
// delay(10);
// Serial.write(Cmd);
} //end if Serial.available
}// end loop
Once I copy this code into the main program the Arduino doesn't communicate. I don't have access to an oscilloscope to see what is actually happening on the bus. The main program uses interrupts to count the encoder pulses but even without any encoder input there is no communication. I have tried both the RS232 and RS485 without success. Below is the main program code with the above code inserted that doesn't recognize Serial.available. The attached picture of the serial monitor shows that the subroutine GetDuctWidth is called but the Serial.available doesn't see any data.
Am I missing something? Any help would be greatly appreciated.
#include <SoftwareSerial.h>
#define RS485_DIR_PIN 4
#include <RotaryEncoder.h>
int dimension = 0;
const int HomeSensor = 5;
const int driveout = 6;
const int drivein = 7;
const int SetMark5 = 8; // Input pin from PLC to start Drive positioning
const int DriveSet = 9; // Pin for Drive Set (Stop Drive)
const int Speed = 10; // Speed output in on pin 6
int DuctWidth = 0;
int newPos = 0;
int HomeOffset = 358; // This is the offset that the proximity sensor is away from actual zero position(4.25" * 84.116 pulses per inch)
int SpeedChange = 50; // Variable to change from High Speed to Low Speed
boolean Mark5_Set = false;// false is Drive is not in position
boolean Home = true; // Home true = Drive has not homed, sensor is high when no proximity present
boolean SpeedHigh = false; //false = low speed
// Setup a RoraryEncoder for pins A2 and A3:
RotaryEncoder encoder(A2, A3);
/********************************************************************************************************
VARIABLES DEFINITION FOR RS232
********************************************************************************************************/
unsigned char Cmd;
unsigned char Terminate = "$00";
unsigned char i;
float Duct;
void setup() {
pinMode(RS485_DIR_PIN, OUTPUT); //Set RS485 direction pin as output
digitalWrite(RS485_DIR_PIN, LOW); //Set RS485 chip as receiver
Serial.begin(9600);
//MCU send some message to wifi bee throutht software serial
while (!Serial)
{
; // wait for serial port to connect. Needed for Leonardo only
}
digitalWrite(RS485_DIR_PIN, HIGH); //Set RS485 as transmitter
//delay(10);
pinMode(driveout, OUTPUT);
pinMode(drivein, OUTPUT);
pinMode(DriveSet, OUTPUT);
pinMode(Speed, OUTPUT);
pinMode(SetMark5, INPUT);// Input to start set arms process( PLC is a sink only output so reverse the logic)
pinMode(HomeSensor, INPUT); // Proximity Sensor Input
Mark5_Set = 0;
//Serial.begin(57600); RS232 Baudrate is 9600
Serial.println("SimplePollRotator example for the RotaryEncoder library.");
/*Serial.print("Home Cycle");
Serial.print(Home);
Serial.println();
*/
delay (2000);// delay startup till PLC wakes up
digitalWrite(Speed, LOW); //Initialize speed to slow(LOW)
if (Home != digitalRead(HomeSensor)) { //Check to verify that Drive is not already at Home
do // Drive out until the proximity sensor changes
{
digitalWrite(drivein, LOW);
digitalWrite(driveout, HIGH );
Home = digitalRead(HomeSensor);
delay (50); // wait long enough for sensor to stablize
} while (Home == false);
}
while (digitalRead(HomeSensor) == true) { // If not Home drive motor in until home(Proximity sensor is sink so True = arms not home)
digitalWrite(driveout, LOW);// Drive motor to Home
digitalWrite(drivein, HIGH);// Drive is always out from home position at startup
int Temp = digitalRead(HomeSensor);// Read Proximity Sensor
if (Temp == false) {// Drive has reached home
digitalWrite(drivein, LOW); // Stop both in & out
delay (2000);// Delay long enough for drive to stop before reversing
encoder.setPosition(HomeOffset); // Reset newPos to HomeOffset
}
newPos = encoder.getPosition();// Read encoder value
}
PCICR |= (1 << PCIE1); // This enables Pin Change Interrupt 1 that covers the Analog input pins or Port C.
PCMSK1 |= (1 << PCINT10) | (1 << PCINT11); // This enables the interrupt for pin 2 and 3 of Port C.
} // setup()
void loop()
{
GetDuctWidth(); // Check if Duct Width has changed
delay(100);
if (digitalRead(SetMark5) != true) { // if operator pushes Set_Mark5 start a new cycle (Output from PLC is sink only,Pin is normally high and pulled low when puhed)
Mark5_Set = false;
digitalWrite(DriveSet, LOW);// Sent Flag indicator to PLC that Drive is NOT set
Serial.print("Start New Cycle ");
Serial.print(Mark5_Set);
Serial.println();
}
while (Mark5_Set == false) {// loop until Mark5_Set is True
DriveMotor ();// Output control to motor
} //if (Mark5_Set == false){
}//loop
void DriveMotor() { // Determine direction and speed to drive motor
newPos = encoder.getPosition();// Read encoder value
if (DuctWidth != newPos) {
Serial.print("newPos = ");
Serial.print(newPos);
Serial.println();
Serial.print("DuctWidth = ");
Serial.print(DuctWidth);
Serial.println();
if (newPos < DuctWidth) {// drive out
if (newPos < DuctWidth - SpeedChange) { // If newPos is not close to DuctWidth then high speed
SpeedHigh = true;
digitalWrite(Speed, HIGH);
Serial.print("Speed = ");
Serial.print(SpeedHigh);
Serial.println();
}
else
{ SpeedHigh = false;// new position is close to current position so slow drive down
digitalWrite(Speed, LOW);
}
digitalWrite(driveout, HIGH);
digitalWrite(drivein, LOW);
}//if newPos < DuctWidth
if (newPos > DuctWidth) {// drive in
if (newPos > DuctWidth + SpeedChange ) { // If newPos is not close to DuctWidth then high speed
SpeedHigh = true;
digitalWrite(Speed, HIGH);
}
else
{ SpeedHigh = false;// new position is close to current position so slow drive down
digitalWrite(Speed, LOW);
}
digitalWrite(driveout, LOW);
digitalWrite(drivein, HIGH);
}// if (newPos > DuctWidth)
} // if (DuctWidth != newPos)
if ( DuctWidth == newPos) {
Mark5_Set = true;
Serial.print("Stop Motor Output");
Serial.print(Mark5_Set);
Serial.println();
digitalWrite(driveout, LOW);
digitalWrite(drivein, LOW);
digitalWrite(DriveSet, HIGH);// Stop Drive signal to PLC
} // if( DuctWidth == newPos)
} // Drive Motor
void GetDuctWidth() {
Serial.println("Hello,this is RS232&RS485 Shield testing program.");
digitalWrite(RS485_DIR_PIN, LOW); //Set RS485 as receiver
if (Serial.available())
{
Serial.println("Serial Available");
float TempDuct = Serial.parseFloat();
if (TempDuct != Duct) {
Serial.println(" TempDuct ");
Serial.println(TempDuct);
if (Serial.find(Terminate)) {
Duct = TempDuct;
}// end Serial.find
}// end if(TempDuct != Duct)
digitalWrite(RS485_DIR_PIN, HIGH);
// delay(10);
// Serial.write(Cmd);
} //end if Serial.available
}// end GetDuctWidth