Prop shield speaker conflict with Touchread function under battery power?

Status
Not open for further replies.

WShawn

Well-known member
Hi:

With the help of others on this and other forums and a friend who's much more adept at coding than I am I'm VERY close to nailing down the code and circuit I need to finalize the electronics for this PKE meter prop I've been working on since, literally, 1993.

My last hurdle is getting my touch switches to work correctly when the circuit is under battery power. My breadboarded prototype works fine when the circuit is powered through USB, but when I power it through my batteries the touch switches stop working when I have a speaker connected to the speaker connections of the prop shield (or I touch one of those contacts). I'm guessing this is a grounding issue of some sort, and I'm hoping that the addition of a diode or capacitor or something somewhere will solve this problem.

I have a Prop Shield LC soldered to a Teensy 3.2. In simplified terms, when activated (either through a touchRead function or mechanical switch) a series of 7 LEDs chase, a pair of servos are sent to a certain angle, and a sound effect plays from the flash memory on the Prop Shield, played through a speaker connected to the Prop Shield's speaker connections.

As a test I modified my breadboard and sketch to use mechanical switches, powered by five 1.2V 2/3A size rechargeable NiMH batteries. These batteries match those used in the original prop, and I like the weight they add to the prop. I'm using a LM340T-5 to step down the 6.2V of those batteries to something more optimal for a Teensy 3.2. Everything works fine under battery power when trigged by mechanical switches.

You can see the setup in action at this link (I can embed only two videos in a post):

https://www.youtube.com/watch?v=n_DcSHE55Uo

The following video shows the system using touch switches (connected to pins 0 and 1, along with ground) to activate the functions, which emulates the actual prop. In this setup the Teensy, Prop Shield and LEDs are driven by the USB power supply while the servos are powered by the NiMH batteries. Again, everything is working as it should. Note that there's an additional touchRead switch attached to pin 23. This allows me to change the way the LED speed is determined, either using preset values or controlled via a pot connected to pin 14.


This is the code we're using to run this setup:

Code:
#include <Servo.h> 
#include <ChaseLEDs.h>
#include <Audio.h>
#include <Wire.h>
#include <SPI.h>
#include <SD.h>
#include <SerialFlash.h>

// GUItool: begin automatically generated code
AudioPlaySerialflashRaw playFlashRaw1; //xy=149,388
AudioMixer4 mixer1; //xy=445,386
AudioOutputAnalog dac1; //xy=591,379
AudioConnection patchCord1(playFlashRaw1, 0, mixer1, 0);
AudioConnection patchCord2(mixer1, dac1);
// GUItool: end automatically generated code


#define NACELLE_RATE         14    // Analog input for reading the nacelle chase rate
#define NACELLE_CHASE_LEN    8     // Length of nacelle chase, 1..6
#define NACELLE_MIN_PERIOD   25    // Minimum time to advance the nacelle chase (milliseconds)
#define NACELLE_MAX_PERIOD   250   // Maximum time to advance the nacelle chase (milliseconds)
#define NACELLE_DIM_VALUE    0      // Value for dimming previous LED in chase, 0..255

// ensure LEDs do not chase by default
boolean chaseOn = false;

// Output pins to use for the nacelle chase
byte nacelleChasePins[8] = {15, 16, 17, 18, 19, 20, 21, 24}; // Pin 24 is not connected to leave blank spot in sequence


// Mode definitions and default
const int CLASSIC = 0;
const int SHAWN = 1;
int currentMode = SHAWN;

// Keep track of the current wing states, don't care about closed state
const int HALF = 0;
const int FULL = 1;
int wingState;

// NacelleChaseLEDs Class definiation based on the ChaseLEDs Class
class NacelleChaseLEDs : public ChaseLEDs
{
  public:
    NacelleChaseLEDs(const byte *pins, int num)
      : ChaseLEDs(pins, num, 0) {}
  protected:
    void advance(byte prevPin, byte nextPin)
    {
      digitalWrite(previousPin(2), LOW);
      analogWrite(prevPin, NACELLE_DIM_VALUE);
      if (chaseOn)
      {
        digitalWrite(nextPin, HIGH);
      }
      if (currentMode == CLASSIC)
      {
      setAdvanceTime(map(analogRead(NACELLE_RATE), 0, 1023, NACELLE_MIN_PERIOD, NACELLE_MAX_PERIOD));
      //digitalWrite(13, !digitalRead(13)); // toggle the LED  <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
      }
      else // Shawn Mode
      {
        if (wingState == HALF)
        {
          setAdvanceTime(250);
        }
        else
        {
          setAdvanceTime(25);
        }
      }
    }
};

// Instantiating a NacelleChaseLEDs object named nacelleChase
NacelleChaseLEDs nacelleChase(nacelleChasePins, NACELLE_CHASE_LEN);

// Touch sensor pin definations
const int touchPinFull = 0;     // pin for touch FULL
const int touchPinHalf = 1;     // pin for touch HALF
const int touchPinMode = 23;    // pin for touch MODE switching

// Set the default touch sensor states
int touchStateHalf = 0;
int touchStateFull = 0;

// Mode Touch button state definitions
const int TOUCHED = 1;
const int UNTOUCHED = 0;

int currentModeTouchState = UNTOUCHED;
int previousModeTouchState = UNTOUCHED;
int lastModeToggle = millis();


// create servo object to control a servo 
Servo myservoL;  // left wing servo
Servo myservoR;  // right wing servo

void setup()
{
  dac1.analogReference(EXTERNAL); // much louder!
  delay(50); // time for DAC voltage stable
  Serial.println ("===> DAC1 Enabled"); 
  pinMode(5, OUTPUT);
  Serial.println ("PIN 5 SET AS OUTPUT");
  digitalWrite(5, HIGH); // turn on the amplifier
  delay(10); // allow time to wake up
  Serial.println ("PIN 5 SET HIGH");

  // Audio connections require memory to work. For more
  // detailed information, see the MemoryAndCpuUsage example
  AudioMemory(8);

  // Set initial volume
  mixer1.gain(0, 0.5f);
  
  // Start SerialFlash
  if (!SerialFlash.begin(6))
  {
    while (1)
  {
    Serial.println ("Cannot access SPI Flash chip");
    delay (1000);
  }
  }

  
  myservoL.attach(9); // left wing servo pin def
  myservoR.attach(10); // right wing servo pin def
  

 
  pinMode(15, OUTPUT);  //Wing LED
  pinMode(16, OUTPUT);  //Wing LED
  pinMode(17, OUTPUT);  //Wing LED
  pinMode(18, OUTPUT);  //Wing LED
  pinMode(19, OUTPUT);  //Wing LED
  pinMode(20, OUTPUT);  //Wing LED
  pinMode(21, OUTPUT);  //Wing LED
  pinMode(2, OUTPUT);  // Status Left LED FUll
  pinMode(3, OUTPUT);  // Status Right LED HALF
  
  pinMode(touchPinFull, INPUT); //TouchFull
  pinMode(touchPinHalf, INPUT); // Touch Half
  pinMode(touchPinMode, INPUT); // Touch Mode
  
  Serial.begin(38400); // initialize serial comms
  Serial.println("SHAWN mode enabled");
}




void toggleMode()
{
  if (currentMode == SHAWN)
  {
    currentMode = CLASSIC;
    Serial.println("CLASSIC mode enabled");
  }
  else
  {
    currentMode = SHAWN;
    Serial.println("SHAWN mode enabled");
  }
}

void loop()
{
  touchStateFull = touchRead(touchPinFull);
  touchStateHalf = touchRead(touchPinHalf);
  if (touchStateFull < 1500) // If no touch (returns below 1500) go to next if statement.  If touched (returns over 1500) else (Full Wings) happens  WINGS AT HOME, NO LIGHTS
  {
    if (touchStateHalf < 1500) // If no touch (returns below 1500) this block happens.  If touched (returns over 1500) else (Half Wings) happens  WINGS AT HOME, NO LIGHTS
    { 
      //Serial.println("Nothing touched");
      if (currentModeTouchState == UNTOUCHED) digitalWrite(2, LOW); //Status FULL LEFT LED OFF
      digitalWrite(3, LOW); //Status HALF RIGHT LED OFF
      digitalWrite(15, LOW);  //Wing LED OFF
      digitalWrite(16, LOW);  //Wing LED OFF
      digitalWrite(17, LOW);  //Wing LED OFF
      digitalWrite(18, LOW);  //Wing LED OFF
      digitalWrite(19, LOW);  //Wing LED OFF
      digitalWrite(20, LOW);  //Wing LED OFF
      digitalWrite(21, LOW);  //Wing LED OFF
      myservoL.write(20);   // Servo home position
      myservoR.write(140);  // Servo home position
      chaseOn = false;
      if (playFlashRaw1.isPlaying()) playFlashRaw1.stop();
     } 
    else
    {
      // TouchPinHalf 1 is touched  WINGS HALF UP, LIGHTS
      //Serial.println(analogRead(NACELLE_RATE));
      digitalWrite(3, HIGH);  // Status LED on
      myservoL.write(80);  // Servo half up
      myservoR.write(80);  // Servo half up
      chaseOn = true;
      wingState = HALF;
      if (!playFlashRaw1.isPlaying()) playFlashRaw1.play("PKE_HALF.RAW");
    }
  } 
  else
  {
    // TouchPinFull 0 is touched  WINGS FULL UP, LIGHTS
    //Serial.println(analogRead(NACELLE_RATE));
    digitalWrite(2, HIGH);  // Status LED on
    myservoL.write(140); // Servo Full Up
    myservoR.write(20);  // Servo Full Up
    chaseOn = true;
    wingState = FULL;
    if (!playFlashRaw1.isPlaying()) playFlashRaw1.play("PKE_FULL.RAW");
  }

  int touchVal = touchRead(touchPinMode);
  if (touchVal > 1500)
  { // Mode Touch Button is TOUCHED during this loop
    currentModeTouchState = TOUCHED;
    int timeSinceToggle = millis() - lastModeToggle;
    // check that timeSinceToggle > 50 to avoid delicate touches from bounching back and forth between modes
    if (currentModeTouchState != previousModeTouchState && timeSinceToggle > 50)
    {
      // state has changed from UNTOUCHED to TOUCHED and we need to take action
      //Serial.println("Mode Button Touched");
      digitalWrite(2, HIGH);
      toggleMode();
      lastModeToggle = millis();
    }
    previousModeTouchState = TOUCHED;
  }
  else   
  {
    // Mode Touch Button is UNTOUCHED during this loop
    currentModeTouchState = UNTOUCHED;
    if (currentModeTouchState != previousModeTouchState)
    {
      // state has changed from TOUCHED to UNTOUCHED and we need to take action
      digitalWrite(2, LOW);
      lastModeToggle = millis();
    }
    previousModeTouchState = UNTOUCHED;
    //Serial.println(touchVal);
    
  }
  
  nacelleChase.loop();
}

This video shows the same setup using the same code as above but powered entirely by the batteries. As in the version using mechanical pushbuttons the batteries are regulated down to 5V before going into Vin on the Teensy, and all 6V go to the servos. As shown in the video nothing works as long as the speaker is hooked up to the Prop Shield (even if just one lead is connected). As soon as I disconnect both speaker leads the touch switches work, triggering the LED chaser and servos. Touching one of the wires I've soldered to the speaker connections also causes the system to stop working. Clipping a long wire to one of the speaker outputs makes it behave erratically.


As I wrote above, this looks like some sort of grounding issue, but I don't have the electronic chops to troubleshoot this more than I've shown here. I can post a schematic if that would be helpful.

Any thoughts or suggestions would be greatly appreciated.

Thanks.

Shawn Marshall
 
Further research leads me to believe that the audio amplifier on the Prop Shield is interfering with the touchRead functionality when a speaker is hooked up or those wires are touched. If I comment out the activation of that amp in line 107 of my code, keeping everything else the same, the touch switches will activate the lights and the servos and play the sound files under battery power with the speaker hooked up. Obviously, without the amp, you can't actually hear those sound files.

So is this approach a dead end? This is a handheld prop, so I can't have it plugged into an outlet or whatever. Is there any way to isolate the amp on the Prop Shield LC to keep it from messing up the touchRead function?

Any help or suggestions or alternative approaches would be greatly appreciated.

Thank you.

Shawn Marshall
 
The audio amplifier of the prop shield is a class D type which will naturally stray lots of RF over the speaker output. This RF, although inaudible in the speaker, might well interfere with the RF based touch sensing.
First would be to move the touch stuff as far away as possible from the speaker and its cables and keeping the speaker cables as short as possible to reduce their transmitter antenna side effects.
Second, a symmetrical pi-LC filter as RF suppressor could be added to the audio output of the prop shield.
 
Hello Theremingenieur:

Thanks so much for the reply, I really appreciate you taking time to respond. I assume by your username you dabble in Theremins? I guess you'd know all about audio amps and RF.

Based on your reply I shortened the wires I'd been using from around 70cm to around 12cm by removing the clip-on jumpers I'd been using and soldering my test speaker directly to the setup. That alone got my setup mostly working. The touch switches now work under battery power, but they're a little twitchy. I might try lowering the threshold on the touchRead function to see if I can get those to be more stable.

I might be able to move the inputs for the touch sensors to the other end of the Teensy, gaining maybe 3cm more distance. I'm not clear on whether the issue is where the touch wires connect to the Teensy or where they are in relation to the enclosure and speaker position. This is a fairly small handheld prop, so I can't put a lot of distance between the components.

Would using some sort of shielded wire help suppress the RF, like if I cannibalized some old headphone wire that had a braided mesh around the leads?

I Googled symmetrical pi-LC filter and got a bunch of technical details beyond my understanding. In practical terms are you talking about a discrete component, like the ones shown here:

https://www.digikey.com/products/en...1&k=Pi+filter&pageSize=100&pkeyword=Pi+filter

If so, is there a spec amongst these 340 items I should be looking for? I assume it wouldn't have to handle a ton of current.

Thanks again for your help.

Shawn
 
Yes, I‘ve acquired a certain reputation as an expert in the Theremin domain. When you ask professional Theremin players about a half French half German guy called Thierry, you can almost be sure that they know me in person or have at least heard about me...

Moving the touch inputs towards the other end of the Teensy will for sure give another improvement without additional cost. You could also try to use a 2 wire shielded cable for the speaker: use the two wires for the + and - speaker signals, and connect the shielding to GND at the Teensy side and let it unconnected at the speaker side.
Don‘t use shielded cables for the touch pins! The additional capacitance of the shielding will lower the touch sensitivity.

The filters which you have found at digikey are mostly power supply filters. A LC pi filter for the speaker output to kill the specific RF interference between the spectrum spread class D switching frequencies and the variable TSI oscillator would have to be custom computed and designed. It’s rather complex and space consuming and I mentioned it only as a kind of last resort if everything else fails.

I don‘t know how you will build the touch contacts in your project. On battery operated devices, RF based touch sensing suffers always from the lack of true grounding. That‘s why the sensitivity with single touch electrodes is reduced in this case. Can you imagine to implement the touch contacts as split or dual electrodes, so that the user will always touch two contacts which look like one? For example 2 half circles or a smaller circle with a ring around (as were the really first sensor keys in the 1970s)? With this electrode style, and always one of both connected to the touch pin and the other to the Teensy’s GND pin, the touch response when both are touched together will also be greatly improved.
 
Thanks again for offering your expertise in this area. Do you play the theremin or just build them? I'm of course familiar with the scores to The Day the Earth Stood Still and Good Vibrations.

Here's a video of the current setup:


This mockup uses the touch contacts installed into the shell of the prop (the PKE meter from Ghostbusters). The original prop, built in the 80s, used resistive touch switches, which I have been able to duplicate with some transistors, a cap and a resistor. Getting the touchRead function to behave reliably would reduce the number of components I need to fit into the prop and really streamline things.

In this case each pair of contacts includes a connection to ground along with a connection to the specified Touch input on the Teensy. Right now I'm using the touch inputs on pins 0, 1 and 23, at the same end as the speaker connections. I'll try moving those to pins 15-17. Currently, if I sometimes don't make good contact with the contacts on the handle (made from bent paper clips) the servos will overshoot and lock up the circuit.

To be clear, the fact that the actual amp appears to live right in the middle of the prop shield isn't the main factor, it's where the wire connections are? My concern is that once this is all crammed into this enclosure the problems could crop up again.

Best.

Shawn
 
I play and teach the Theremin, I develop add-on circuits for existing Theremin models, and I’m developing new instruments.

Back to your problem: The physical location of the amp chip isn’t important. It’s all about reducing the interferences by shortening the wiring and to put the speaker and touch wires most apart from another to reduce capacitive and inductive coupling and stray effects.

The PKE Meter from Ghost Busters? Isn’t that a little childish? ;)
 
I don't think it's recommended to set the touchRead pins modes. If you don't set the mode, the I/O functionality will remain in its default disabled state. touchRead() uses different circuitry.

You probably got the wiring right, but this is my understanding. The touchRead functionality works by measuring a change in capacitance. The touchRead inputs should be connected to a conductor that will be near but not necessarily touching something like a finger that can capacitively couple with it when present. This conductor is single ended. Just a wire like an antenna. A thin layer of insulator can separate the touchRead wire from the finger. I'm not an electrical engineer, but I'm guessing a low resistance path to ground might prevent the touchRead circuit to charge up the finger so that it could measure discharge and thus a change in capacitance.
 
Touching a touch pin will definitively increase the capacitance seen by the TSI oscillator. In an optimal environment (touch circuit grounded AND touching person grounded), this additional capacitance will be between 100pF and 150pF. If you operate your touch sensor on batteries, oscillator grounding gets almost lost, so that only a small parasitic capacitance is seen in series with the touch capacitance and thus the overall capacitance change can never be bigger than the small parasitic capacitance. That’s why adding a small grounded secondary electrode which must be touched at the same time will solve the problem since it bypasses that parasitic series capacitance and thus restores the full variation.

Besides of that, it is absolutely wrong to set whatever pin mode for a touch pin, it must be left floating (Reference manual!) because any CMOS input or output and any pull up or pull down resistor added to it by the MUX would block the correct TSI oscillator operation.
 
Thanks again for the replies, I appreciate it.

Thanks for the clarification regarding the importance of the wires over the physical location of the amp. In my latest prototype I moved the inputs of the touch contacts to pins 15-17. I haven't found any shielded cable kicking around.

The circuit appears to active reliably via the touchReads, but I'm getting some intermittent overshoot of my servos when triggered this way.


I can't get them to overshoot using mechanical switches. My battery array reads as 6.3V on my old old Radio Shack multi tester. I wonder if that extra .3V is making the servo motor move too fast for the internal pot to read the spot to stop the servo at the proper angle. I think I've damaged one of the servos as it now chatters in its HOME position. I'm not sure what one would do to slow down the servos just a bit. Add a resistor in there?

Not being an electronics expert, I don't know whether I should be using a capacitor or something to condition my battery power supply. Maybe the quick current draw of the activated servos is causing a problem.

If I can't get this touchRead approach to be 100% solid I'll probably go back to the resistive touch switches that work reliably in my 1989 build of this prop.

Regarding my "childish" hobby, I suppose I'm just a kid at heart. I'm 56 years old. I was 23 when Ghostbusters came out, and a friend and I might have been amongst the first, if not THE first hobbyists to build screen accurate Proton Packs in September-October of 1984. I built a pretty-good PKE meter in 1989 based on very crude references. When I acquired some good photos of the actual prop, along with the shoe polisher on which it was based, I endeavored to make a more-accurate version. I've been slowly working on it since the early 90s. I still enjoy showing off my work by wearing my gear at screenings of Ghostbusters in the Portland area and attending the Rose City Comic Con here.

Cheers.

Shawn
 
Is it possible that the position pots in the servos are simply oxydated and thus give wrong position information? Or, if it is really a timing problem, why not move them in two steps, doing a first move to 90%, wait a few ms and then move them to the end position?

Please don't feel offended by my (I admit) slightly provocative mentioning of "childish". Everybody has naturally the right to live his childhood dreams. Please accept my apologies!
 
Is it possible that the position pots in the servos are simply oxydated and thus give wrong position information? Or, if it is really a timing problem, why not move them in two steps, doing a first move to 90%, wait a few ms and then move them to the end position?

Please don't feel offended by my (I admit) slightly provocative mentioning of "childish". Everybody has naturally the right to live his childhood dreams. Please accept my apologies!

Hi:

I don't think it's a sudden onset of dirty pots causing this erratic behavior. It seems like a strange coincidence that the servos would start misbehaving at the same time I was testing this touchRead setup (though it looks like some teeth broke on one of the servos, I'm assuming when it overshot during a test). I think I will look into adapting and incorporating the Servo sweep sketch into my sketch for this prop. That way I can control how fast it reaches the predetermined angle rather than rotate there as fast as the motor will send it.

I didn't really take the "childish" comment as an insult. Why would someone taking the time to help me also insult me? That said, I wouldn't say it was a childhood dream to build replicas of props. It's just a hobby, a creative outlet. Some people golf. Some people paint. Some people build and play theremins. I happen to play volleyball and build props and models.

Cheers.

Shawn
 
Status
Not open for further replies.
Back
Top