Stacking ThingShield w/ RS232 Shield

arduino
thingshield

#1

I’m going to try to interface with my Denon x6200w through RS232 using a Sparkfun Redboard (Uno), ThingShield, and RS232 Shield. I’m new to the world of adding, let alone stacking, shields, so I’m concerned that the ThingShield and RS232 shield won’t stack to the Redboard.

The only development I’ve done is on a RPi/External Relay/Python scripting, so hopefully someone who knows more about Arduino pinouts take a look at the physical pin # requirements and confirm I’ll be OK?

I’ll be using the ST_Anything sketches/library from @ogiewon, and I’ve got it all loaded up and ready in the IDE for parts to arrive.

And, if all goes well I’ll post up a detailed tutorial on how this all works out!


LAN Device Type (Denon Receiver) - HTTP GET Update Frequency Help
(ActionTiles.com co-founder Terry @ActionTiles; GitHub: @cosmicpuppy) #2

I don’t know about that particular RS232 shield, but you just need a simple RS-232 to Serial converter.

I am using this to interface my Arduino + ThingShield to my Epson Projector:

Works great!


#3

Thanks for the idea! I cancelled the RS232 shield and will go this route. I, currently have an Epson 2040 (no RS232 port :frowning: ), but am planning on getting a 5040 shortly after it releases. It looks like it will carry the same RS232 port as it’s predecessor. My ultimate goal here with the ThingShield is to get some reliable and instant on/off feedback for lighting automation when I fire up the Denon or Epson.

Would you be willing to go into a bit of detail setting this up (Maybe you posted a thread and I just can’t find it)? One thing I’m not sure of is what pins I would need solder the 232->Serial converter to.


(ActionTiles.com co-founder Terry @ActionTiles; GitHub: @cosmicpuppy) #4

I’ve never posted the details, just a link to the ad hoc code … I guess that still could be helpful as it will refer to the PIN numbers. The second most lazy thing I can do is take a picture of the breadboarded hardware.

/**
 * Notes:
 *   - Screen can get out of sync with GUI because of assumed "Next State".
 *        - Projector has a verification (the trigger signal), so it is better.
 *        - But with no verification, might as well assume the screen is in the last requested spot.
 */

#define MYVERSION "v1.0.2-beta+002"
/*****************************************************************************
 * @file
 * @brief
 * 2015/8/02 - A few modifications by CosmicPuppy to send responses for every command (on, off).
 */
#include <RCSwitch.h>
#include <SoftwareSerial.h>   //TODO need to set due to some weird wire language linker, should we absorb this whole library into smartthings
#include <SmartThings.h>

#define PIN_THING_RX    3
#define PIN_THING_TX    2

SmartThingsCallout_t messageCallout;    // call out function forward decalaration
SmartThings smartthing(PIN_THING_RX, PIN_THING_TX, messageCallout, "", false);  // constructor

/*
 * NB: Can't use SoftwareSerial reliably because it conflicts with ThingShield running at 2400 BAUD.
 *     Perhaps we could get everything running at 2400 BAUD or 9600 BAUD, but I think speed of Shield and Projector aren't configurable.
 */
//SoftwareSerial projecSerial(4, 5); // RX, TX
#define projecSerial Serial

int ledPin = 13;
bool isDebugEnabled = true;    // enable or disable debug in this example

#define down  12
#define up    11
#define pause 10
#define RCPIN 10

int holdDuration = 200; // duration of the relay on "press"
int waitDuration = 100; // duration of the relay between "presses".

int inputPin = 7; // 12vDC mono trigger signal input from Projector
bool projectorOn = false;
// bool projectorUpdate = false; /* Let status of Projector be unsent until we see it change? */
int inputPinSum = 0; // We will sum the value of input pin over several samples to make sure it is really ON or really OFF.
int loopCount = 0;

/* TODO: These could be made on/off configuration options from the SmartThings Device Tiles! */
/*       or change them to #define */
bool screenAutoOn  = true;  // Localized automatic screen down/on when Projector ON  if true.
bool screenAutoOff = false; // Localized automatic screen up/off  when Projector OFF if true.

bool screenIsOn = false; // Attempt to avoid extra Screen On attempts in SOME automatic calls.

RCSwitch myRCSwitch = RCSwitch(); /* Remote Control RF Radio */


/**
 * setup
 */
void setup()
{
  /* Remote Control RF Radio Setup */
  myRCSwitch.enableTransmit(RCPIN);
  
  /* Input trigger from Projector */
  analogReference(DEFAULT);
  pinMode(inputPin, INPUT);
  digitalWrite(inputPin, LOW); // Must be LOW else always get 1. Is this Pulldown enabled?
  
  /* Set mode for Hardware Pins */
  pinMode(ledPin, OUTPUT);
  digitalWrite(ledPin, HIGH);

  pinMode(down, OUTPUT);
  digitalWrite(down, LOW);

  pinMode(up, OUTPUT);
  digitalWrite(up, LOW);

  // projecSerial.begin(9600);  // This line breaks everything. Must conflict with ThingShield Software Serial.

  updateProjector();

  if (isDebugEnabled)
  { // setup debug serial port
    Serial.begin(9600);
    Serial.print("Version"); Serial.println(MYVERSION);
    Serial.println("Setup.");
  }
} /* setup() */


/**
 * loop
 */
void loop()
{
  
  /* We will allow a few "missed" signal values 5 out of 50 and still count as ON. */
  inputPinSum += digitalRead(inputPin);
  if ( loopCount <= 50 && inputPinSum > 45 ) {
    // Serial.println( "Signal still ON." );
    if ( !projectorOn ) {
      projectorOn = true;
      // projectorUpdate = true;
      updateProjector();
      if ( screenAutoOn && !screenIsOn ) screenOn();
      screenIsOn = false; // Reset local Screen Status to be sure it will turn on next *automated* attempt.
    }
    loopCount = 0;
    inputPinSum = 0;
  } else if ( loopCount >= 50 && inputPinSum < 5 ) {
    // Serial.println( "Signal is OFF." );
    if ( projectorOn ) {
      projectorOn = false;
      //projectorUpdate = true;
      updateProjector();
      if ( screenAutoOff && screenOff ) screenOff();
    }
    loopCount = 0;
    inputPinSum = 0;
  }
  if ( loopCount > 50 ) { loopCount = 0; inputPinSum = 0; }
  loopCount ++;

  smartthing.run();
} /* loop() */


/**
 * doublePress
 */
void doublePress( int whichButton )
{
  singlePress( whichButton );
  singlePress( whichButton );
}


/**
 * singlePress
 */
void singlePress( int whichButton )
{
//  digitalWrite(whichButton, HIGH);
//  delay(holdDuration);
//  digitalWrite(whichButton, LOW);
//  delay(waitDuration);
  switch (whichButton) {
    case up:
      myRCSwitch.send(4750754, 24);
      break;
    case down:
      myRCSwitch.send(4750756, 24);
      break;  
    case pause:
      myRCSwitch.send(4750760, 24);
      break;  
  }
  delay(waitDuration);
}


/**
 * screenOn() - Screen Down
 */
void screenOn()
{
  smartthing.shieldSetLED(0, 1, 0); // green

  digitalWrite( up, LOW);  // Be certain to lift the other button.
  doublePress( down );

  smartthing.send("screenOn");
  Serial.println("Sent: screenOn");
  // Serial.println( smartthing.shieldGetLastNetworkState() ); // Extra debugging if necessary.
}


/**
 * screenOff() - Screen Up
 */
void screenOff()
{
  smartthing.shieldSetLED(0, 0, 1); // blue

  digitalWrite( down, LOW);  // Be certain to lift the other button.  
  doublePress( up );

  smartthing.send("screenOff");
  Serial.println("Sent: screenOff");
  // Serial.println( smartthing.shieldGetLastNetworkState() ); // Extra debugging if necessary.
}



/**
 * projecSendMsg() - Send message to Projector.
 * Currently hard coded for multiple tries since this doesn't hurt.
 */
void projecSendMsg( char* message )
{
  byte inByte;
  
  Serial.println( "Attempting message: " ); Serial.println( message );
  /* Empty the input buffer (mostly ERR messages from the Projector, probably). */
  while( projecSerial.available() ) { inByte = Serial.read(); };
  delay(300);
  projecSerial.print( message ); projecSerial.print( "\r" );
  projecSerial.println( "" );
  /* Do it a second time for good measure. */
  delay(300);
  while( projecSerial.available() ) { inByte = Serial.read(); };
  projecSerial.println( message );
  delay(300);
  while( projecSerial.available() ) { inByte = Serial.read(); };
  delay(300);
  projecSerial.print( message ); projecSerial.print( "\r" );
  projecSerial.println( "" );
  while( projecSerial.available() ) { inByte = Serial.read(); };
  /* TODO: We could confirm that no ":ERR" response received. */
}

/**
 * projecOn() - Projector On
 */
void projecOn()
{
  int inByte = 0;
  smartthing.shieldSetLED(0, 2, 1); // green

  /* Watching for Projector reponses may or may not be useful. I guess useful in case remote control is used in a separate function. */
  /* TODO: We could first read "PWR?" to get result ":PWR=00" or ":PWR=01 or 02" or ":ERR" */

  projecSendMsg( "PWR ON" );

  /* We do this here to let the screen start movement ASAP. */
  if ( screenAutoOn && !screenIsOn ) {
    screenOn();
    screenIsOn = true; // Assume success in order to avoid next automated attempt.
  }

  /* TODO: we don't do next two lines unless we check projecSerial output. Instead we check Signal Trigger. */
  // smartthing.send("projecOn");
  // Serial.println("Sent: projecOn");
  // Serial.println( smartthing.shieldGetLastNetworkState() ); // Extra debugging if necessary.
}


/**
 * projecOff() - Projector Off
 */
void projecOff()
{
  int inByte = 0;
  smartthing.shieldSetLED(0, 1, 2); // blue

  /* Watching for Projector reponses may or may not be useful. I guess useful in case remote control is used in a separate function. */
  /* TODO: We could first read "PWR?" to get result ":PWR=00" or ":PWR=01 or 02" or ":ERR" */
  projecSendMsg( "PWR OFF" );

  /* We do this here to let the screen start movement ASAP. */
  if ( screenAutoOff && screenIsOn ) { 
    screenOff();
    screenIsOn = false; // Assume success in order to avoid next automated attempt.
  }

  /* TODO: we don't do next two lines unless we check projecSerial output. Instead we check Signal Trigger */
  // smartthing.send("projecOff");
  // Serial.println("Sent: projecOff");
  // Serial.println( smartthing.shieldGetLastNetworkState() ); // Extra debugging if necessary.
}


/**
 * disable() - Stop Screen (TODO: could also disable SmartThings control).
 */
void disable()
{
  smartthing.shieldSetLED(1, 0, 0); // red

//  digitalWrite( up, LOW);  // Be certain to lift the other button.  
//  doublePress( down );
//  singlePress( up );

  /* TODO: For pause (stop), singlePress() should be sufficient! */
  doublePress( pause );
  
  smartthing.send("disable");       // send message to cloud
  Serial.println("Sent: disable");
  // Serial.println( smartthing.shieldGetLastNetworkState() );
}


/**
 * enable() - Enable SmartThings (TODO: Just resets from disable for now.).
 */
void enable()
{
  smartthing.shieldSetLED(1, 2, 1); // 

//  digitalWrite( up, LOW);  // Be certain to lift the other button.  
//  doublePress( down );
//  singlePress( up );

  /* TODO: For pause (stop), singlePress() should be sufficient! */
  doublePress( pause );

  smartthing.send("enable");       // send message to cloud
  Serial.println("Sent: enable");
  // Serial.println( smartthing.shieldGetLastNetworkState() );
}


/**
 * updateProjector State in SmartThings
 * TODO: Perhaps name SmartThings outgoing messages with "state" or something.
 */
void updateProjector() {
  if (projectorOn) {
    Serial.println( "Sending: projecOn" );
    smartthing.send("projecOn");
  } else {
    Serial.println( "Sending: projecOff" );
    smartthing.send("projecOff");
  }
} /* updateProjector */


/**
 * messageCallout
 * TODO: Move projectorUpdate outside this function as well as callers in loop().
 */
void messageCallout(String message)
{
  Serial.print("In messageCallout.");
  // if debug is enabled print out the received message
  if (isDebugEnabled)
  {
    Serial.print("Received message: '");
    Serial.print(message);
    Serial.println("' ");
  }

  if (message.equals("screenOn"))
  {
    screenOn();
  }
  
  if (message.equals("screenOff"))
  {
    screenOff();
  }

  if (message.equals("projecOn"))
  {
    projecOn();
  }
  
  if (message.equals("projecOff"))
  {
    projecOff();
  }
  
  if (message.equals("disable"))
  {
    disable();
  }
  
  if (message.equals("enable"))
  {
    enable();
  }

  if ((message.substring(0,10)).equals("projecMsg:")) {
    String projecMsg = message.substring(10);
    char* projecMsgC = new char[projecMsg.length()+1];
    projecMsg.toCharArray(projecMsgC,projecMsg.length()+1);
    //Serial.print( "Received request to send message: " );
    //Serial.println( projecMsgC );
    projecSendMsg( projecMsgC );
  }
  
} /* messageCallout() */


/* =========== */
/* End of File */
/* =========== */

#5

This looks great! Thank you - I’m just interested on Power ON and Power OFF functions, so this helps a lot.


(Dan) #6

@tgauchat @kars85

Sounds like an interesting project.

Terry - Is your project 1-way communications only? That is, does it only receive data from the ThingsShield and then send serial commands out the RS-232 port to your device?

@bravenel Bruce and I worked through a similar SmartThings to RS-232 bridge using an Arduino and ThingShield. In Bruce’s case, he needed to have BI-Directional communications, where the Arduino would have to listen to both the ThingShield and the RS-232 port simultaneously. This is not possible using the SoftwareSerial library. To solve the issue, Bruce upgraded to an Arduino MEGA 2560 board, and then used my “SmartThings” ThingShield library to allow his project to use one of the MEGA’s hardware serial ports for the ThingShield communications. That freed up the SoftwareSerial library for his RS-232 shield to be able to listen continuously. He may have even ditched the Software Serial library altogether in favor of using another Hardware Serial port on the Arduino MEGA 2560 for better performance and reliability.

So, the lesson learned here should be - Buy an Arduino MEGA 2560 (or clone) and use the 3 extra HW Serial ports when needed. Also, having 8k of RAM instead of just 2k is often very helpful as well.

Dan


(ActionTiles.com co-founder Terry @ActionTiles; GitHub: @cosmicpuppy) #7

It’s mostly one way, but I don’t there’s anything in my configuration that precludes bi-directional. (Of course, having extra hardware serials is always a good thing; and sometimes the RAM is needed for big projects).

I run the RS-232 off the default hardware serial (Pins 0,1) on the Uno (which is also the USB/Debugging serial, but that’s ok).

SmartThings ThingShield uses Software Serial on different pins.


(Dan) #8

Ah! That makes perfect sense! So, software serial is only used for one device. The UNO’s HW Serial is used for the other.

Good compromise!


#9

I have a few things on order, and appreciate both you guys’ help (@tgauchat & @ogiewon) thus far. @tgauchat, if you don’t have your board all bundled up in a project box, would you be able to upload a quick picture?

Basically, all I am gunning for is reliable status reporting to ST when my receiver is powered on/off by my IR remote. I don’t drive my theater setup by phone/tablet (yet). :slight_smile:


(ActionTiles.com co-founder Terry @ActionTiles; GitHub: @cosmicpuppy) #10

It’s an embarrassing rats nest since I’ve not been motivated to solder it to a protoboard, but I’ll snap a pic and see if it needs a few labels added.

As you can tell from the code, the Arduino has 3 duties:

  1. 315 Mhz transmitter for projection screen.
  2. 12v (damped down to 4v) Trigger input from the Projector as a simple failsafe to activate the screen down state.
  3. RS232 for sending on, off and brightness profile commands to the projector.

All topped off with the handy ThingShield and a custom Device Type Handler (not shared here yet).


(Dan) #11

Take a look at Bruce’s work as he has a very simple lightweight Arduino sketch for a ST to RS-232 bridge.


#12

Really starting to make some mental headway here while I wait. I’m seriously planning on getting the Epson with RS232 as soon as it hits the market. After all, that is the crux of my lighting automation anyway. The only reason I went with trying to interface with the Denon was because it was the only component that offered RS232 comms.

Not knowing how you turn your epson on (IR, HTTP, etc…) I’m going to probably ask a stupid question. In your setup, if you power the Epson on or off using the factory remote, the power status quickly gets reflected within ST?


(ActionTiles.com co-founder Terry @ActionTiles; GitHub: @cosmicpuppy) #13

I set it up so that it can be turned on manually (ie, regular IR remote) or from a SmartThings relayed command (including Alexa) which has the Arduino send “ON” message via RS232.

The change of state could possibly be detected from a message sent from the RS232, but instead the Arduino just watches the traditional 12v Trigger out line (also available on many AV receivers). The Arduino then immediately updates SmartThings with the power state.


(Michael) #14

@tgauchat how is this connected to your Arduino? I am considering automating my old receiver that has a rs232 connector and curious what this is. Is this the IR equivalent output I have on my receiver? It’s a small headphone jack output. So curious the type of output on your projector and how you are “damping” it down.

Thanks!


(ActionTiles.com co-founder Terry @ActionTiles; GitHub: @cosmicpuppy) #15

I’m referring to a dumb 12v “trugger out”, not an IR relay signal (which also may come in ⅛" jack format). Figure out which one you have (what’s your receiver model).

Trigger output is either 0v or 12v (12v = receiver or projector is active so it is used by sister devices like external amplifiers, screens, etc).

It’s a mono ⅛" headphone jack on my projector, so I just chopped off one end of a spare cable I had around (I hoard old parts), so it’s bare wires on the other end.

Next solder in 3 resistors in the right combination to follow Ohm’s Law, and that lowers the voltage from 12v to 4v, so that it doesn’t blow the 5v based digital or analog inputs in an Arduino.

I’m sure it would help when I finally draw a circuit diagram. I took a couple pics last night, but they’re just good enough for me to reference and use Fritzing.


Meanwhile if you have RS232 you’ll have both input and output of simple text commands (on, off, input select, mode, volume up, down, etc.)… Much more powerful than trigger signal only, but I use both. Modern AV equipment uses Ethernet or WiFi instead (or in addition).


(Michael) #16

Doh! Should have looked a little closer, yes I have 2 12v trigger outputs. Thanks for the clarification.


#17

Ready to go boys and girls - just waiting on brown Santa to deliver the 5040. Many thanks to @tgauchat and @ogiewon.

I’m going to try the stock On/Off Shield device type and see how that works. Hard to picture the full integration with the main component missing.


(Dan) #19

Any update on your project? Always interesting to hear what others have come up with!