Works on Nano, stops with ATtiny45

Hi!

I'm working on something like compass with tilt compensation (nevermind).

I made program and tested it on arduino Nano (since there is no problem with serial controll). After some calibration and test i've decide to move it to attiny.

And something went wrong... it stoped to work. I've modified somehow the sketch to debug it. As i have connected LED's to it already, i made function to blink and found out that the problem is with HMC5883L (compass) - stops on "!compass.begin()" loop connected in parallel with MPU6050 (accelerometer + gyro).

Can there be something that makes it not working with different cpu in scetch or library?

scetch

#include <Wire.h>
#include <HMC5883L.h>
#include <MPU6050.h>

HMC5883L compass;
MPU6050 accel;

// AtTiny
const int lLed = 1;
const int cLed = 3;
const int rLed = 4;

const int serialOn = 0;

//Nano
/*const int lLed = 3;
const int cLed = 5;
const int rLed = 6;

const int serialOn = 1;*/

int head = 0;

void setup() {
  // put your setup code here, to run once:
  if(serialOn){
    Serial.begin(9600);
  }
  
  pinMode(lLed, OUTPUT);
  pinMode(rLed, OUTPUT);
  pinMode(cLed, OUTPUT);

  //blinkOnce();
  
  // Initialize MPU6050
  while(!accel.begin(MPU6050_SCALE_2000DPS, MPU6050_RANGE_2G)){
    delay(100);
  }

  //blinkOnce();
  
  // Enable bypass mode
  accel.setI2CMasterModeEnabled(false);
  accel.setI2CBypassEnabled(true) ;
  //accel.setSleepEnabled(false); //default: false

  //blinkOnce();

  // Initialize Initialize HMC5883L
  while (!compass.begin()){
    delay(100);
    blinkOnce();
  }

  blinkOnce();
  
  // Set measurement range (default)
  //compass.setRange(HMC5883L_RANGE_1_3GA);

  // Set measurement mode (default)
  //compass.setMeasurementMode(HMC5883L_CONTINOUS);

  // Set data rate (10b), default - 15HZ
  //compass.setDataRate(HMC5883L_DATARATE_30HZ);

  // Set number of samples averaged (10b), default - 1
  compass.setSamples(HMC5883L_SAMPLES_8);

  // Set calibration offset. See HMC5883L_calibration.ino
  compass.setOffset(17, -64); 

  blinkOnce();
}

void blinkOnce(){
  
  digitalWrite(lLed, HIGH);
  digitalWrite(cLed, HIGH);
  digitalWrite(rLed, HIGH);

  delay(100);
  
  digitalWrite(lLed, LOW);
  digitalWrite(cLed, LOW);
  digitalWrite(rLed, LOW);
  delay(100);
}

void loop() {
  // put your main code here, to run repeatedly:
  Vector mag = compass.readRaw();
  Vector acc = accel.readRawAccel(); 
  //Vector acc = {0.0, 0.0, 0.0};
  //normAccel.YAxis;

  float ax,ay,az,cx,cz,cy;
  const float multip = 0.005493164/57;

  //ay-z in radians
  ax = acc.XAxis * multip;
  ay = acc.YAxis * multip;
  az = acc.ZAxis * multip;
  
  cx = mag.XAxis;
  cy = mag.YAxis;
  cz = mag.ZAxis;

  float xh,yh;

  /*Serial.print("AX: ");
  Serial.print(ax);
  Serial.print(" AY: ");
  Serial.print(ay);
  //Serial.print(" AZ: ");
  //Serial.print(az);
  Serial.print(" | ");*/

  if(serialOn){
    //Serial.print("CX: ");
    Serial.print(cx);
    //Serial.print(" CY: ");
    Serial.print(" ");
    Serial.print(cy);
    //Serial.print(" CZ: ");
    //Serial.print(cz);
    //Serial.print(" | ");
  }
  
  xh=cx*cos(ay)+cy*sin(ay)*sin(ax)-cz*cos(ax)*sin(ay);
  yh=cy*cos(ax)+cz*sin(ax);

  //xh=cx*(cos(ax) - 0.85)/0.15;
  //yh=cy*(cos(ay) - 0.85)/0.15;

  /*Serial.print("ayf: ");
  Serial.print(ayf);
  Serial.print(" axf: ");
  Serial.print(axf);
  Serial.print(" | ");*/
 
  //xh=cx*ayf+cy*ayf*axf-cz*axf*ayf;
  //yh=cy*axf+cz*axf;

  /*if(serialOn){
    Serial.print("cos ay: ");
    Serial.print(cos(ay));
    Serial.print(" cos ax: ");
    Serial.print(cos(ax));
    Serial.print(" sin ay: ");
    Serial.print(sin(ay));
    Serial.print(" sin ax: ");
    Serial.print(sin(ax));
    Serial.print(" | ");
  }*/
  
  head=atan2((double)yh,(double)xh) * (180 / PI) -90; // angle in degrees
  head += 3;
  if (head<0){head += 360;}
  //head += 360;

  /*int ax,ay,az,cx,cz,cy;
  MMA7660.getValues(&ax,&ay,&az);
  HMC.getValues(&cx,&cz,&cy);
 
  float xh,yh,ayf,axf;
  ayf=ay/57.0;//Convert to rad
  axf=ax/57.0;//Convert to rad
  xh=cx*cos(ayf)+cy*sin(ayf)*sin(axf)-cz*cos(axf)*sin(ayf);
  yh=cy*cos(axf)+cz*sin(axf);
 
  var_compass=atan2((double)yh,(double)xh) * (180 / PI) -90; // angle in degrees
  if (var_compass>0){var_compass=var_compass-360;}
  var_compass=360+var_compass;
 
  return (var_compass);*/

  /*if(serialOn){
    Serial.println(head);
  }*/
  
  digitalWrite(lLed, LOW);
  digitalWrite(cLed, LOW);
  digitalWrite(rLed, LOW);

  if(head < 10 || head > 350){
    digitalWrite(cLed, HIGH);
  }else if(head >= 10 && head < 180){
    digitalWrite(lLed, HIGH);
  }else if(head <= 350 && head >= 180){
    digitalWrite(rLed, HIGH);
  }

  delay(100);

  //blinkOnce();
}

HMC lib attached.

HMC5883L.cpp (5.78 KB)

Ok, it seems that i have RAM problem - sketch (compiled for nano) uses 349 bytes, while on attiny45 has only 256. I'll try to slim it down and then report.

Nope. It uses now 220B and still does not work.

220bytes of RAM or ROM? Keep in mind that the amount the compiler tells you about is only the globals. All non globals need there memory on run time as well.

RAM i belive...

my current scetch:

attached file

Szkic używa 4272 bajtów (71%) pamięci programu. Maksimum to 6012 bajtów.
Zmienne globalne używają 36 bajtów pamięci dynamicznej.

For digispark it is only 36 bytes (?!).

The problem was this part:

if ((fastRegister8(HMC5883L_REG_IDENT_A) != 0x48)
    || (fastRegister8(HMC5883L_REG_IDENT_B) != 0x34)
    || (fastRegister8(HMC5883L_REG_IDENT_C) != 0x33))
    {
  return false;
    }

Which was never true on digispark.

replaced it with:

while(readRegister8(0x0A) != 0x48){
      blinkOne(lLed, 100);
    }
    while(readRegister8(0x0B) != 0x34){
      blinkOne(cLed, 100);
    }
    while(readRegister8(0x0C) != 0x33){
      blinkOne(rLed, 100);
    }

and it blinks two or three times and go on, but it still does not work.

The program is supposed to turn on left or right led if "compass" is not heading north, else central led. But it mainly jumps from left to right and almost never central.

I thought it has something to do with int, so changed it to int16_t (or int8_t if it was not needed to be that long), float to double.

No more idea...

kompas-kompensacja-moje4unified.ino (10.2 KB)

Sorry it's ATtiny45 not 85, sorry for my mistake.