Momentary Buttons Work Sporadically When Connected To Battery. 100% On USB

Status
Not open for further replies.
Basically as my title says. I have to momentary buttons wired to my Teensy 3.5, on Pins 32 and 34, sharing a common ground where the battery is connected to. I have also moved their ground to a pin that wasn't the same one the battery was on. I am using this schematic as a reference, with my only changes being that every ground is connected to the topmost ground pin on the teensy and I have a 4 pin Male/Female connector as opposed to a 5 pin.

4f6a4cf1576e4fcda24785b415f37ce0c3ec90ad.png

I uploaded a simple file that turns on the built in LED when my main button is pressed, and when connected to USB power via my computer, it works just fine. But when connected to my battery, the LED will stay on when I left go of the button, seemingly until whenever it wants to stop. Sometimes twisting my JST cables shuts it off, sometimes it's just a few seconds; I have no idea why.

I use a 5 pin JST connector to connect the 5 pins to that male connector in the schematic (Power up, Power down, Ground from battery, Ground from plug to teensy, and data.) The 2 grounds are sliced together on the other end before merging into one cable that connectors to the radial connector.

My only thought is that there is something wrong with that wiring on my 5 pin connector. Or that the battery is much more drained than I had thought and I haven't assembled my charger yet to charge it. Any thoughts would be greatly appreciated! Thank you!

Full Source Code and my git repo if you'd rather look at it there:

Code:
#include <Audio.h>
#include <Wire.h>
#include <SPI.h>
#include <SD.h>
#include <SerialFlash.h>
#include <WS2812Serial.h>
#include "MPU9250.h"

// GUItool: begin automatically generated code
AudioPlaySdWav playSdWav3;     //xy=154,392
AudioPlaySdWav playSdWav2;     //xy=159,355
AudioPlaySdWav playSdWav1;     //xy=384,2003
AudioMixer4 mixer1;            //xy=456,406
AudioOutputTDM tdm1;           //xy=558,2017
AudioOutputAnalogStereo dacs1; //xy=659,403
AudioConnection patchCord3(playSdWav2, 0, mixer1, 1);
AudioConnection patchCord4(playSdWav2, 1, mixer1, 0);
AudioConnection patchCord5(playSdWav1, 0, mixer1, 2);
AudioConnection patchCord6(playSdWav1, 1, mixer1, 3);
AudioConnection patchCord7(mixer1, 0, dacs1, 0);
AudioConnection patchCord8(mixer1, 0, dacs1, 1);
// GUItool: end automatically generated code

#define onOffButton PIN_A13
#define colorButton PIN_A15
#define SDCARD_CS_PIN BUILTIN_SDCARD
#define SDCARD_MOSI_PIN 11 // not actually used
#define SDCARD_SCK_PIN 13  // not actually used
#define PIN 1
//Colors
#define OFFCOLOR 0x000000
#define GREEN 0x17ff00
#define RED 0xFF0000
#define BLUE 0x12e3f0
#define PURPLE 0x9c11cc
#define PINK 0xe359c7
#define YELLOWORANGE 0xef8d0f
#define WHITE 0xffffff

const int numled = 144;
int previousMillisInterrupt = 0;
int previousMillisAccel = 0;
int currentMillisAccel = 0;
int xSwingThresholdPositive = 3;
int zSwingThresholdPositive = 3;
int xSwingThresholdNegative = -3;
int zSwingThresholdNegative = -3;
int clashThreshold = 28;
int clashThresholdNegative = -28;
int colorFlag = 0;
//How many colors do we have, with the exception of OFF
const int NUMOFCOLORS = 7;
int colorInUse = GREEN; //Green by default

int function = 0; //what action are we going to perform
int status = 0;   //global status int we can use for initializations and usages

byte drawingMemory[numled * 3];         //  3 bytes per LED
DMAMEM byte displayMemory[numled * 12]; // 12 bytes per LED

WS2812Serial leds(numled, displayMemory, drawingMemory, PIN, WS2812_GRB);
MPU9250 IMU(Wire, 0x68);

void buttonPress()
{
  unsigned long currentMillisInterrupt = millis();
  if (currentMillisInterrupt - previousMillisInterrupt >= 1000)
  {
    function++;
    Serial.print("Function is now: ");
    Serial.println(function);

    if (function >= 4)
    {
      function = 0;
    }
    previousMillisInterrupt = currentMillisInterrupt;
  }
}

void switchColors()
{
  byte colorByte = 0;

  Serial.println("Switching colors");

  colorFlag++;
  if (colorFlag > NUMOFCOLORS)
  {
    colorFlag = 0;
  }
  colorByte = 1;

  switch (colorFlag)
  {
    //GREEN
  case 0:
    if (colorByte == 1)
    {
      for (int i = 1; i < numled; i++)
      {
        leds.setPixel(i, GREEN);
        leds.setPixel(i + 1, GREEN);
        i++;
        leds.show();
      }
      colorInUse = GREEN;
      colorByte = 0;
    }
    break;
    //BLUE
  case 1:
    if (colorByte == 1)
    {
      for (int i = 1; i < numled; i++)
      {
        leds.setPixel(i, BLUE);
        leds.setPixel(i + 1, BLUE);
        i++;
        leds.show();
      }
      colorInUse = BLUE;
      colorByte = 0;
    }
    break;
    //RED
  case 2:
    if (colorByte == 1)
    {
      for (int i = 1; i < numled; i++)
      {
        leds.setPixel(i, RED);
        leds.setPixel(i + 1, RED);
        i++;
        leds.show();
      }
      colorInUse = RED;
      colorByte = 0;
    }
    break;
    //PURPLE
  case 3:
    if (colorByte == 1)
    {
      for (int i = 1; i < numled; i++)
      {
        leds.setPixel(i, PURPLE);
        leds.setPixel(i + 1, PURPLE);
        i++;
        leds.show();
      }
      colorInUse = PURPLE;
      colorByte = 0;
    }
    break;
    //PINK
  case 4:
    if (colorByte == 1)
    {
      for (int i = 1; i < numled; i++)
      {
        leds.setPixel(i, PINK);
        leds.setPixel(i + 1, PINK);
        i++;
        leds.show();
      }
      colorInUse = PINK;
      colorByte = 0;
    }
    break;
  case 5:
    if (colorByte == 1)
    {
      for (int i = 1; i < numled; i++)
      {
        leds.setPixel(i, YELLOWORANGE);
        leds.setPixel(i + 1, YELLOWORANGE);
        i++;
        leds.show();
      }
      colorInUse = YELLOWORANGE;
      colorByte = 0;
    }
    break;
  case 6:
    if (colorByte == 1)
    {
      for (int i = 1; i < numled; i++)
      {
        leds.setPixel(i, WHITE);
        leds.setPixel(i + 1, WHITE);
        i++;
        leds.show();
      }
      colorInUse = WHITE;
      colorByte = 0;
    }
    break;
  }
}

void setup()
{
  // put your setup code here, to run once:
  Serial.println("Setup start");
  Serial.begin(9600);

  //Set LEDs to Off
  leds.begin();
  for (int i = numled; i > -10; i--)
  {
    leds.setPixel(i, OFFCOLOR);
    leds.show();
  }
  leds.show();

  pinMode(LED_BUILTIN, OUTPUT);
  pinMode(onOffButton, INPUT);
  pinMode(colorButton, INPUT);
  delay(250);

  // start communication with IMU
  status = IMU.begin();
  if (status < 0)
  {
    Serial.println("IMU initialization unsuccessful");
    Serial.println("Check IMU wiring or try cycling power");
    Serial.print("Status: ");
    Serial.println(status);
    while (1)
    {
    }
  }

  AudioMemory(8);
  SPI.setMOSI(SDCARD_MOSI_PIN);
  SPI.setSCK(SDCARD_SCK_PIN);
  if (!(SD.begin(SDCARD_CS_PIN)))
  {
    while (1)
    {
      Serial.println("Unable to access the SD card");
      delay(500);
    }
  }
  mixer1.gain(0, 0.1f);
  mixer1.gain(1, 0.1f);

  attachInterrupt(digitalPinToInterrupt(onOffButton), buttonPress, FALLING);
  attachInterrupt(digitalPinToInterrupt(colorButton), switchColors, FALLING);

  Serial.println(playSdWav1.isPlaying() ? "TRUE" : "FALSE");
  if (playSdWav1.isPlaying() == false)
  {
    Serial.println("Playing startup sound");
    playSdWav1.play("SETUP.WAV");
    delay(1000); // wait for library to parse WAV info
  }

  Serial.println("Setup complete");
}

//Empty, because it stays off (I'd unplug the battery here to save power)
void stayOff() {}

void turnOn()
{
  digitalWrite(LED_BUILTIN, HIGH);

  if (playSdWav1.isPlaying() == false)
  {
    Serial.println("Playing on sound");
    playSdWav1.play("POWERON.WAV");
    //Seems this value is dependent on how long my ignition sound is
    delay(10);
    // Don't play sound here. It overrides the ignition for some reason
    //  playSdWav2.play("HUM.WAV");
    //  delay(10);
  }

  for (int i = 1; i < numled; i++)
  {
    leds.setPixel(i, colorInUse);
    leds.setPixel(i + 1, colorInUse);
    i++;
    leds.show();
  }

  function = 2;
}

void turnOff()
{
  digitalWrite(LED_BUILTIN, LOW);

  Serial.println("Playing off sound");
  playSdWav1.play("POWEROFF.WAV");
  delay(10);

  for (int i = numled; i > -10; i--)
  {
    leds.setPixel(i, OFFCOLOR);
    leds.show();
  }

  function = 0;
}

void swing()
{
  int index = random(0, 15);

  const char *swing = "";

  switch (index)
  {
  case 0:
    swing = "SWING1.WAV";
    break;
  case 1:
    swing = "SWING2.WAV";
    break;
  case 2:
    swing = "SWING3.WAV";
    break;
  case 3:
    swing = "SWING4.WAV";
    break;
  case 4:
    swing = "SWING5.WAV";
    break;
  case 5:
    swing = "SWING6.WAV";
    break;
  case 6:
    swing = "SWING7.WAV";
    break;
  case 7:
    swing = "SWING8.WAV";
    break;
  case 8:
    swing = "SWING8.WAV";
    break;
  case 9:
    swing = "SWING10.WAV";
    break;
  case 10:
    swing = "SWING11.WAV";
    break;
  case 11:
    swing = "SWING12.WAV";
    break;
  case 12:
    swing = "SWING13.WAV";
    break;
  case 13:
    swing = "SWING14.WAV";
    break;
  case 14:
    swing = "SWING15.WAV";
    break;
  case 15:
    swing = "SWING16.WAV";
    break;
  default:
    swing = "SWING1.WAV";
    break;
  }

  if (playSdWav2.isPlaying() == false)
  {
    Serial.print("Playing swing sound: ");
    Serial.println(swing);
    playSdWav1.play(swing);
    delay(10);
  }
}

void clash()
{
  int index = random(0, 2);
  const char *clash = "";

  switch (index)
  {
  case 0:
    clash = "CLASH1.WAV";
    break;
  case 1:
    clash = "CLASH2.WAV";
    break;
  case 2:
    clash = "CLASH3.WAV";
    break;
  }

  if (playSdWav2.isPlaying() == false)
  {
    Serial.println("Playing clash sound");
    playSdWav1.play(clash);
    delay(10);
  }
}

void readAccelerometer()
{
  IMU.readSensor();

  float gyroX = IMU.getGyroX_rads();
  float gyroZ = IMU.getGyroZ_rads();
  float accelerationTotal = IMU.getAccelX_mss() + IMU.getAccelY_mss() + IMU.getAccelZ_mss();

  // Serial.print("Accelertaion Total: " );
  // Serial.println(accelerationTotal, 6);

  if (accelerationTotal >= clashThreshold || accelerationTotal <= clashThresholdNegative)
  {
    Serial.println("We've clashed");
    clash();
  }

  if (gyroX >= xSwingThresholdPositive || gyroX <= xSwingThresholdNegative)
  {
    Serial.println("SWINGING!");
    swing();
  }
  if (gyroZ >= zSwingThresholdPositive || gyroZ <= zSwingThresholdNegative)
  {
    Serial.println("SWINGING!");
    swing();
  }

  delay(100);
}

void poweredOn()
{
  if (playSdWav1.isPlaying() == false)
  {
    Serial.println("Playing HUM sound");
    playSdWav1.play("HUM.WAV");
    delay(10);
  }

  readAccelerometer();
}

void loop()
{

  // switchColors();
  // put your main code here, to run repeatedly:
  switch (function)
  {
  case 0:
    stayOff();
    break;
  case 1:
    turnOn();
    break;
  case 2:
    poweredOn();
    break;
  case 3:
    turnOff();
    break;
  default:
    break;
  }
}
 
Last edited:
Sometimes hard to say without actually seeing your actual program?

Example things to check:
How are your defining these pins and checking them?

Are they defined as INPUT_PULLUP? and you are checking for them to go low?

Are you using the bounce like library to handle case of signal bouncing up and down?


Does your code have in it something like: while (!Serial) ;
which would hang forever when you are plugged into battery but not serial?

Or another variation of:
Code:
elapsedMillis em = 0;
while (!Serial && (em < 3000)) ;
Which would wait for 3 seconds every time it is called for the Serial object to be available...
(elapsedMillis can also be replaced by saving start time and doing your own millis()-start_time...

Or??? again can only throw darts.
 
Sometimes hard to say without actually seeing your actual program?

Right, sorry. I'll update my original Post with the full code.

How are your defining these pins and checking them?
Are they defined as INPUT_PULLUP? and you are checking for them to go low?

See my edit in the main post for code. But they are defined as #define variables and then called with just INPUT, not INPUT_PULLUP. They have interrupts attached to trigger their respective functions during loop().

Are you using the bounce like library to handle case of signal bouncing up and down?

I don't believe so no. I've never heard of that before.

Does your code have in it something like: while (!Serial) ;
which would hang forever when you are plugged into battery but not serial?

Or another variation of:

And no. None of that
 
Any chance you're running all of Teensy's current though extremely thin, low-quality wires? Like these...

cheapwires.jpg

If you have wires like this, try measuring them with an ohm meter. Some are so thin, so poorly constructed that they'll measure several ohms. If you run a pulsing current that averages 50 to 100 mA, where the brief pulses are much higher, it's pretty easy to get large changes in voltage due to the high resistance of the hair-thin wire.
 
The 2 grounds are sliced together
I presume this should be "spliced". If the ground wires are only twisted together, they probably aren't making good electrical contact. They should be soldered. Twisting the JST cables may cause the spliced grounds to glitch.


A few notes about your code:

- you never use playSdWav3

- The default gain for mixer inputs is 1 so the total gain for mixer1 is 2.2 (because 2 and 3 are 1 each). It would be best to keep the total gain to no more than 1. Set the gains for inputs 2 and 3 on the mixer1 to 0.4

- although you don't explicitly use debouncing, your buttonPress function responds to a button press no more than once a second so contact bounce shouldn't be a problem.

- I presume that case 8 should use SWING9.WAV

- random(0,15) will produce numbers from 0 to 14, so "case 15:" will never be reached. You need random(0, 16).

Pete
 
How are your defining these pins and checking them?
Are they defined as INPUT_PULLUP? and you are checking for them to go low?
See my edit in the main post for code. But they are defined as #define variables and then called with just INPUT, not INPUT_PULLUP. They have interrupts attached to trigger their respective functions during loop().

You definitively need pullup resistors on those pins!
 
Any chance you're running all of Teensy's current though extremely thin, low-quality wires? Like these...

View attachment 19139

If you have wires like this, try measuring them with an ohm meter. Some are so thin, so poorly constructed that they'll measure several ohms. If you run a pulsing current that averages 50 to 100 mA, where the brief pulses are much higher, it's pretty easy to get large changes in voltage due to the high resistance of the hair-thin wire.

Replaced the connector's wires with stronger 18 gauge (as opposed to the 26 it was before) and it's the same result unfortunately :/.
 
You definitively need pullup resistors on those pins!

I will look into getting some resistors to see if it helps. Why are they needed though? And that's not a snarky "but why" statement. This is my first project with an arduino/teensy so I'm genuinely curious as to why they're needed since they work just fine on USB power and not battery.
 
I will look into getting some resistors to see if it helps. Why are they needed though? And that's not a snarky "but why" statement. This is my first project with an arduino/teensy so I'm genuinely curious as to why they're needed since they work just fine on USB power and not battery.

On that topic, switching the button's read to INPUT_PULLUP seems to have fixed my issue. At least at a first glance. Does the 3.5 have internal pullup resistors? I couldn't find any definitive answer to that..
 
I will look into getting some resistors to see if it helps. Why are they needed though? And that's not a snarky "but why" statement. This is my first project with an arduino/teensy so I'm genuinely curious as to why they're needed since they work just fine on USB power and not battery.

Without a pullup resistor the input pin is connected to nothing(floating), its state is undefined and influenced by different factors. Simply put, the wire attached to the pin acts like an antenna.

By adding an external pullup resistor or enabling the internal one, the input pin's state is set to high(3.3V).
If I'm not mistaken, all pins that can act as a digital pin have an internal pullup and pulldown resistor available.

The fact that it worked with USB might just be a lucky occurrence.
 
Status
Not open for further replies.
Back
Top