ADXL345 Accelerometer does not work on external power

Hi all,
I am making an hourglass (exactly like this https://www.instructables.com/Arduino-Hourglass/). I modified


the code for ADXL345 accelerometer and its seems to work when connected to PC. But when i connect it to external power, everything works except accelerometer so it is not working properly.

#include <TM1637.h>
#include <Adafruit_ADXL345_U.h>
#include "Arduino.h"
#include "LedControl.h"
#include "Delay.h"
#include <Wire.h>

#define MATRIX_A  0
#define MATRIX_B  1

// Values are 260/330/400
//#define ACC_THRESHOLD_LOW 260
//#define ACC_THRESHOLD_HIGH 400

#define ADXL_THRESHOLD_Z 0
#define ADXL_THRESHOLD_X 0

// Matrix
#define PIN_DATAIN 6
#define PIN_CLK 8
#define PIN_LOAD 7

// Accelerometer
#define PIN_X A5
#define PIN_Y A4
Adafruit_ADXL345_Unified accel = Adafruit_ADXL345_Unified();

// Pins Buttons
#define PIN_BUTTON 9
#define PIN_BUTTON2 10

#define PIN_BUZZER 99

// This takes into account how the matrixes are mounted
#define ROTATION_OFFSET 0

// in milliseconds
#define DEBOUNCE_THRESHOLD 200

#define DELAY_FRAME 100

#define MODE_HOURGLASS 0
#define MODE_SETMINUTES 1
#define MODE_SETSECONDS 2

int ADXL345 = 0x53; // The ADXL345 sensor I2C address

float X_out, Y_out, Z_out;  // Outputs

float delayMinutes = 0;
float delaySeconds = 40;
float duracion = 30;
float delayMilisecs = (duracion/60)*1000;
int mode = MODE_HOURGLASS;
int gravity;
LedControl lc = LedControl(PIN_DATAIN, PIN_CLK, PIN_LOAD, 2);
NonBlockDelay d;
int resetCounter = 0;
bool alarmWentOff = false;
int CLK = 12;
int DIO = 11;
unsigned long pulsacion;
TM1637 tm(CLK,DIO);


/**
   Get delay between particle drops (in seconds)
*/
float getDelayDrop() {
  // since we have exactly 60 particles we don't have to multiply by 60 and then divide by the number of particles again :)
  return delayMinutes + delaySeconds/60;
}

coord getDown(int x, int y) {
  coord xy;
  xy.x = x - 1;
  xy.y = y + 1;
  return xy;
}
coord getLeft(int x, int y) {
  coord xy;
  xy.x = x - 1;
  xy.y = y;
  return xy;
}
coord getRight(int x, int y) {
  coord xy;
  xy.x = x;
  xy.y = y + 1;
  return xy;
}



bool canGoLeft(int addr, int x, int y) {
  if (x == 0) return false; // not available
  return !lc.getXY(addr, getLeft(x, y)); // you can go there if this is empty
}
bool canGoRight(int addr, int x, int y) {
  if (y == 7) return false; // not available
  return !lc.getXY(addr, getRight(x, y)); // you can go there if this is empty
}
bool canGoDown(int addr, int x, int y) {
  if (y == 7) return false; // not available
  if (x == 0) return false; // not available
  if (!canGoLeft(addr, x, y)) return false;
  if (!canGoRight(addr, x, y)) return false;
  return !lc.getXY(addr, getDown(x, y)); // you can go there if this is empty
}



void goDown(int addr, int x, int y) {
  lc.setXY(addr, x, y, false);
  lc.setXY(addr, getDown(x, y), true);
}
void goLeft(int addr, int x, int y) {
  lc.setXY(addr, x, y, false);
  lc.setXY(addr, getLeft(x, y), true);
}
void goRight(int addr, int x, int y) {
  lc.setXY(addr, x, y, false);
  lc.setXY(addr, getRight(x, y), true);
}


int countParticles(int addr) {
  int c = 0;
  for (byte y = 0; y < 8; y++) {
    for (byte x = 0; x < 8; x++) {
      if (lc.getXY(addr, x, y)) {
        c++;
      }
    }
  }
  return c;
}


bool moveParticle(int addr, int x, int y) {
  if (!lc.getXY(addr, x, y)) {
    return false;
  }

  bool can_GoLeft = canGoLeft(addr, x, y);
  bool can_GoRight = canGoRight(addr, x, y);

  if (!can_GoLeft && !can_GoRight) {
    return false; // we're stuck
  }

  bool can_GoDown = canGoDown(addr, x, y);

  if (can_GoDown) {
    goDown(addr, x, y);
  } else if (can_GoLeft && !can_GoRight) {
    goLeft(addr, x, y);
  } else if (can_GoRight && !can_GoLeft) {
    goRight(addr, x, y);
  } else if (random(2) == 1) { // we can go left and right, but not down
    goLeft(addr, x, y);
  } else {
    goRight(addr, x, y);
  }
  return true;
}



void fill(int addr, int maxcount) {
  int n = 8;
  byte x, y;
  int count = 0;
  for (byte slice = 0; slice < 2 * n - 1; ++slice) {
    byte z = slice < n ? 0 : slice - n + 1;
    for (byte j = z; j <= slice - z; ++j) {
      y = 7 - j;
      x = (slice - j);
      lc.setXY(addr, x, y, (++count <= maxcount));
    }
  }
}



/**
   Detect orientation using the accelerometer

       | up | right | left | down |
   --------------------------------
   400 |    |       | y    | x    |
   330 | y  | x     | x    | y    |
   260 | x  | y     |      |      |
*/
int getGravity() {
  Wire.beginTransmission(ADXL345);
  Wire.write(0x32); // Start with register 0x32 (ACCEL_XOUT_H)
  Wire.endTransmission(false);
  Wire.requestFrom(ADXL345, 6, true); // Read 6 registers total, each axis value is stored in 2 registers
  X_out = ( Wire.read()| Wire.read() << 8); // X-axis value
  X_out = X_out/256; //For a range of +-2g, we need to divide the raw values by 256, according to the datasheet
  Y_out = ( Wire.read()| Wire.read() << 8); // Y-axis value
  Y_out = Y_out/256;
  Z_out = ( Wire.read()| Wire.read() << 8); // Z-axis value
  Z_out = Z_out/256;
  //int x = analogRead(PIN_X);
  //int y = analogRead(PIN_Y);
  //Serial.println(y);
  //Serial.print(y);
  //if (y < ACC_THRESHOLD_LOW)  {
  //  return 0;
  // }
  // if (x > ACC_THRESHOLD_HIGH) {
  //   return 90;
  // }
  //if (y > ACC_THRESHOLD_HIGH) {
  //  return 180;
  //}
  //if (x < ACC_THRESHOLD_LOW)  {
  //  return 270;
  //}
  if (Z_out < ADXL_THRESHOLD_Z)  {
    return 0;
  }
  if (Z_out > ADXL_THRESHOLD_Z)  {
    return 180;
  }
  if (X_out < ADXL_THRESHOLD_X)  {
    return 270;
  }
  if (X_out > ADXL_THRESHOLD_X)  {
    return 90;
  }
}


int getTopMatrix() {
  return (getGravity() == 180) ? MATRIX_A : MATRIX_B;
}
int getBottomMatrix() {
  return (getGravity() != 180) ? MATRIX_A : MATRIX_B;
}



void resetTime() {
  for (byte i = 0; i < 2; i++) {
    lc.clearDisplay(i);
  }
  fill(getTopMatrix(), 60);
  d.Delay(getDelayDrop()*1000);
}

void displayTime(int seconds, int minutes){

    tm.point(1);
    tm.display(3, seconds % 10);
    tm.display(2, seconds / 10 % 10);
    tm.display(1, minutes % 10);
    tm.display(0, minutes / 10 % 10);
}
/**
   Traverse matrix and check if particles need to be moved
*/
bool updateMatrix() {
  int n = 8;
  bool somethingMoved = false;
  byte x, y;
  bool direction;
  for (byte slice = 0; slice < 2 * n - 1; ++slice) {
    direction = (random(2) == 1); // randomize if we scan from left to right or from right to left, so the grain doesn't always fall the same direction
    byte z = slice < n ? 0 : slice - n + 1;
    for (byte j = z; j <= slice - z; ++j) {
      y = direction ? (7 - j) : (7 - (slice - j));
      x = direction ? (slice - j) : j;
      // for (byte d=0; d<2; d++) { lc.invertXY(0, x, y); delay(50); }
      if (moveParticle(MATRIX_B, x, y)) {
        somethingMoved = true;
      };
      if (moveParticle(MATRIX_A, x, y)) {
        somethingMoved = true;
      }
    }
  }
  return somethingMoved;
}



/**
   Let a particle go from one matrix to the other
*/
boolean dropParticle() {
  if (d.Timeout()) {
    d.Delay(getDelayDrop()*1000);
    if (gravity == 0 || gravity == 180) {
      if ((lc.getRawXY(MATRIX_A, 7, 0) && !lc.getRawXY(MATRIX_B, 0, 7)) ||
          (!lc.getRawXY(MATRIX_A, 7, 0) && lc.getRawXY(MATRIX_B, 0, 7))
         ) {
        // for (byte d=0; d<8; d++) { lc.invertXY(0, 0, 7); delay(50); }
        lc.invertRawXY(MATRIX_A, 7, 0);
        lc.invertRawXY(MATRIX_B, 0, 7);
        tone(PIN_BUZZER, 440, 10);
        return true;
      }
    }
  }
  return false;
}



void alarm() {
  for (int i = 0; i < 5; i++) {
    tone(PIN_BUZZER, 440, 200);
    delay(1000);
  }
}



void resetCheck() {
  int z = analogRead(A3);
  if (z > ACC_THRESHOLD_HIGH || z < ACC_THRESHOLD_LOW) {
    resetCounter++;
    Serial.println(resetCounter);
  } else {
    resetCounter = 0;
  }
  if (resetCounter > 20) {
    Serial.println("RESET!");
    resetTime();
    resetCounter = 0;
  }
}



void displayLetter(char letter, int matrix) {
  // Serial.print("Letter: ");
  // Serial.println(letter);

  lc.clearDisplay(matrix);

  if (letter == 'M') {
    lc.setXY(matrix, 1, 4, true);
    lc.setXY(matrix, 2, 3, true);
    lc.setXY(matrix, 3, 2, true);
    lc.setXY(matrix, 4, 1, true);
  
    lc.setXY(matrix, 3, 6, true);
    lc.setXY(matrix, 4, 5, true);
    lc.setXY(matrix, 5, 4, true);
    lc.setXY(matrix, 6, 3, true);
  
    lc.setXY(matrix, 4, 2, true);
    lc.setXY(matrix, 4, 3, true);
    lc.setXY(matrix, 5, 3, true);
  }
  if (letter == 'S') {
    lc.setXY(matrix, 1, 5, true);
    lc.setXY(matrix, 2, 6, true);  
      
    lc.setXY(matrix, 3, 6, true);
    lc.setXY(matrix, 4, 5, true);

    lc.setXY(matrix, 3, 3, true);
    lc.setXY(matrix, 4, 4, true);    
    
    lc.setXY(matrix, 3, 2, true);
    lc.setXY(matrix, 4, 1, true);
  
    lc.setXY(matrix, 5, 1, true);
    lc.setXY(matrix, 6, 2, true); 
  }
}



void renderSetMinutes() {
  fill(getTopMatrix(), delayMinutes);
  displayTime(delaySeconds,delayMinutes);
  displayLetter('M', getBottomMatrix());
}
void renderSetSeconds() {
  fill(getTopMatrix(), delaySeconds);
  displayTime(delaySeconds,delayMinutes);
  displayLetter('S', getBottomMatrix());
}




void knobClockwise() {
  Serial.println("Clockwise");
  if (mode == MODE_SETSECONDS) {
    delaySeconds = constrain(delaySeconds + 1, 0, 59);
    renderSetSeconds();
  } else if (mode == MODE_SETMINUTES) {
    delayMinutes = constrain(delayMinutes + 1, 0, 60);
    renderSetMinutes();
  }
  Serial.print("Delay: ");
  Serial.println(getDelayDrop());
}
void knobCounterClockwise() {
  Serial.println("Counterclockwise");
  if (mode == MODE_SETSECONDS) {
    delaySeconds = constrain(delaySeconds - 1, 0, 59);
    renderSetSeconds();
  } else if (mode == MODE_SETMINUTES) {
    delayMinutes = constrain(delayMinutes - 1, 0, 60);
    renderSetMinutes();
  }
  Serial.print("Delay: ");
  Serial.println(getDelayDrop());
}




void boton1(unsigned long pulsacion){
  if(pulsacion>50000){
      mode = (mode + 1) % 3;
      Serial.print("Switched mode to: ");
      Serial.println(mode);
  
      if (mode == MODE_SETMINUTES) {
        lc.backup(); // we only need to back when switching from MODE_HOURGLASS->MODE_SETMINUTES
        renderSetMinutes();
      }
      if (mode == MODE_SETSECONDS) {
        renderSetSeconds();
      }
      if (mode == MODE_HOURGLASS) {
        lc.clearDisplay(0);
        lc.clearDisplay(1);
        lc.restore();
        resetTime();
      }
    }else{
      if (pulsacion>=500){
        if (mode != MODE_HOURGLASS){
          knobCounterClockwise();
        }
      }
    }
    
  //}
 
  
}


void tiempo1(){
    pulsacion = 0;    
    while(!digitalRead(PIN_BUTTON)){
      pulsacion++;
    }
    boton1(pulsacion);    
}

/**
   Button callback (incl. software debouncer)
   This switches between the modes (normal, set minutes, set hours)
*/
void buttonPush() {
    tiempo1();    
}


volatile unsigned long lastButton2PushMillis;
void button2Push() {
  if ((long)(millis() - lastButton2PushMillis) >= DEBOUNCE_THRESHOLD) {
    if (mode != MODE_HOURGLASS){
      knobClockwise();
    }
  }
}


/**
   Setup
*/
void setup() {
  Serial.begin(9600);

  // while (!Serial) {
  //   ; // wait for serial port to connect. Needed for native USB
  // }

  // setup rotary encoder
  pinMode(PIN_BUTTON, INPUT);
  pinMode(PIN_BUTTON2, INPUT);
  attachInterrupt(digitalPinToInterrupt(PIN_BUTTON), buttonPush, LOW);  
  attachInterrupt(digitalPinToInterrupt(PIN_BUTTON2), button2Push, RISING);
  
  tm.init();
  // set brightness; 0-7
  tm.set(2);  
  displayTime(delaySeconds,delayMinutes);

  randomSeed(analogRead(A0));

  // init displays
  for (byte i = 0; i < 2; i++) {
    lc.shutdown(i, false);
    lc.setIntensity(i, 0);
  }

  resetTime();
}



/**
   Main loop
*/
void loop() {
  delay(DELAY_FRAME);

  // update the driver's rotation setting. For the rest of the code we pretend "down" is still 0,0 and "up" is 7,7
  gravity = getGravity();
  //Serial.print(gravity);
  lc.setRotation((ROTATION_OFFSET + gravity) % 360);

  // handle special modes
  if (mode == MODE_SETMINUTES) {
    renderSetMinutes(); return;
  } else if (mode == MODE_SETSECONDS) {
    renderSetSeconds(); return;
  }

  // resetCheck(); // reset now happens when pushing a button
  bool moved = updateMatrix();
  bool dropped = dropParticle();

  // alarm when everything is in the bottom part
  if (!moved && !dropped && !alarmWentOff && (countParticles(getTopMatrix()) == 0)) {
    alarmWentOff = true;
    alarm();
  }
  // reset alarm flag next time a particle was dropped
  if (dropped) {
    alarmWentOff = false;
  }
}

What external power? It's the only part I think you forgot to provide details for.

connecting pc case's usb ports or phone charger

What is printed on the phone charger AC/DC (wall wart)? Have you tried with another external power source? Are you just using the same USB cable whether using your PC as power supply or the switching wall adapter?

i tried with 67w phone charger and this is the cable im using

Your diagram shows buttons on D9 and D10. Your setup() reads:

  pinMode(PIN_BUTTON, INPUT);
  pinMode(PIN_BUTTON2, INPUT);

but you have no pull down resistors attached to those pushbuttons. Going by this info, you have floating buttons.

You could try:

  pinMode(PIN_BUTTON, INPUT_PULLUP);
  pinMode(PIN_BUTTON2, INPUT_PULLUP);

, remembering that the button logic will now be the reverse of what might seem intuitive.

i changed the code with that but the problem still persists

Does it still work when connected to your PC with that cable but not work when connected to your phone charger, using that same exact cable?
67W wall wart?
What is the voltage/max amperage of the wall wart?
Mine, for example, says 120V (AC) Input, 5V (DC) Output at 2.0A (max current that anything it's attached to may draw through the regulator inside the wall wart).

You're not using the Arduino 5V pin to power all that, are you? Including the LED matrices?
The link to that Instructables says you're using these:

  • 2x 8*8 led matrix MAX7219
    If that's true, you really ought to power those at least, and preferably the entire circuit, using a regulated power stage between your overall power supply and everything else, being sure that all grounds lead back to the overall power supply.

Also, is it an Arduino Nano you're using? Your input voltage should be 7-12V if so.

no, that cable does not work on pc either. On the charger, it says 240V input, 5V(DC) 3A normal output and 5V-20V 6.2A-3.25A Fast Output

Yes, i am using 5V pin to power all that including LED matrices. When i upload the code with data cable the code works perfectly.

i am going to try it with 9V 300mA adapter, is it ok to power it from its usb port?

Then it's quite obvious that the cable is no good.
I'm sure that @hallowed31 will agree

1 Like

i mean the LED matrices and the display works with that cable but not the accelerometer

No dont do that!
The cable you are using is bad
Only use 5V when connectet to he USB port

1 Like

I would start by correcting this cable.
Then you should read the datasheets/info for the Arduino you're using, also the exact modules you have.
My rule of thumb for using the Arduino 5V voltage regulator to power other devices is, input modules like the accelerometer or the popular ultrasonic sensor HC-SR04, usually ok. Output devices using the 5V regulator could be a problem (servos, motors, led modules set to high brightness, Adafruit Neopixels, etc)

I was typing as you responded. You beat me to it (again :wink:)

I'm sorry.
The only problem is that the cables is bad

what should use i instead of it? maybe soldering barrel jack socket to directly into Vin pin and ground?

Take your cable apart, get rid of the barrel connectors and connect the USB A connector directly to the USB mini connector.
Make sure your solder connections are good and check continuity with an ohmmeter/DMM

OR just use the same cable that you use when you connect to the PC