Dissappearing Strings with Attiny85, while no problems with UNO

I have written a program that reads the inputs of a thumb joysticks and send thems over bluetooth.
When trying the code on Arduino Uno Serial.print works as expected, but when I upload the code to Attiny, I face two problems

  • at the function detectJoystickChanges() it is always omitting printing the String message0 or message1.

So UNO prints
UPV,020
DNV,003
LFT,005
KEY,001
and Attiny85 prints
,020
,003
,005
,001

  • Moreover combining Strings doesnt work on my code at Attiny
    So the following btSerial.println(message0 + sensorWert0 + sensorValue0);
    works perfectly at UNO combining all Strings,
    while at Attiny85 is prints empty lines!

Here is my code and any idea, why it fails will be highly appreciated!!

#include <SendOnlySoftwareSerial.h>
SendOnlySoftwareSerial btSerial(3); // TX - Connected to Attiny85
#define baud 9600

const int sensorPin0 = A1;  //Speed - Xout - Attiny Pin 7
const int sensorPin1 = A2;  //Direction - Yout - Attiny Pin 3

const int buttonPin = 0; //Attiny - Attiny Pin 5
const int blinkPin = 1; //Attiny Pin 6

int sensorValue0;
int sensorValue1;
//For the push button
bool buttonValue;

int averageSensor0 = 0;                // the average of Sensor 0
int averageSensor1 = 0;                // the average of Sensor 1

// Variables used to detect changes
int oldSensorValue0 = 0;
int oldSensorValue1 = 0;
int oldButtonValue = 0;

String sensorWert0;
String message0;
String str0;
String sensorWert1;
String message1;
String str1;

void setup() {
  // make the SEL line an input
  pinMode(buttonPin, INPUT);
  // turn on the pull-up resistor for the selectPin line (see http://arduino.cc/en/Tutorial/DigitalPins)
  digitalWrite(buttonPin, HIGH);

  btSerial.begin(baud);
  btSerial.println("Control with Joystick - 2 pots");

  //Average Potentiometers
  btSerial.println("Average Potentiometers");
  //averagePotsInit();
  btSerial.println("Do not touch joystick");
  setAverages();
  btSerial.println("Averaging Potentiometers Completed");

  btSerial.println("Running main loop");
  delay(100);
}

void loop() {
  readPots(); //No correction of pot values
  //printPotReadings();
  ignoreCentralValues();
  correctPots();
  mapValues();
  messageStructure();
  detectJoystickChanges();
  delay(10);
}

void setAverages() {
  readPots();
  averageSensor0 = sensorValue0;
  averageSensor1 = sensorValue1;
  btSerial.print("AverageFound:");
  btSerial.print(averageSensor0);
  btSerial.print("\t"); // prints a tab
  btSerial.println(averageSensor1);
}

void readPots() {
  // read the value from the sensor:
  sensorValue0 = analogRead(sensorPin0);  //Speed
  sensorValue1 = analogRead(sensorPin1);  // Direction
}

void printPotReadings() {
  btSerial.print("Speed:");
  btSerial.print(sensorValue0);
  btSerial.print("\t"); // prints a tab
  btSerial.print("Direction:");
  btSerial.println(sensorValue1);
}

void ignoreCentralValues() {
  int correctionLimit = 3;

  if (sensorValue0 > averageSensor0 - correctionLimit && sensorValue0 < averageSensor0 + correctionLimit)
    sensorValue0 = averageSensor0;

  if (sensorValue1 > averageSensor1 - correctionLimit && sensorValue1 < averageSensor1 + correctionLimit)
    sensorValue1 = averageSensor1;
}

// Correct Pots according to Sebastian
void correctPots() {
  /////////////////////////  Sensor 0 - Speed  ////////////////////////////////////////
  if (sensorValue0 >= averageSensor0) {
    //Up
    sensorValue0 = sensorValue0 - averageSensor0;
    message0 = "UPV";  
  }

  else if (sensorValue0 < averageSensor0) {
    //Down
    sensorValue0 = -(sensorValue0 - averageSensor0);
    message0 = "DNV";
  }

  /////////////////////////  Sensor 1 - Direction ////////////////////////////////////////
  if (sensorValue1 >= averageSensor1) {
    //Left
    sensorValue1 = sensorValue1 - averageSensor1;
    message1 = "LFT";
  }

  else if (sensorValue1 < averageSensor1) {
    //Right
    sensorValue1 = -(sensorValue1 - averageSensor1);
    message1 = "RTV";
  }
}

void mapValues() {
  int mappingSegments = 30;
  sensorValue0 = map(sensorValue0, 0, averageSensor0, 0,  mappingSegments);
  sensorValue1 = map(sensorValue1, 0, averageSensor1, 0,  mappingSegments);
}

void messageStructure() {
  ////////////// sensor value 0 /////////////////////////
  if (sensorValue0 >= 0 && sensorValue0 <= 9) {
    sensorWert0 = ",00";
  }
  else if (sensorValue0 >= 10 && sensorValue0 <= 99) {
    sensorWert0 = ",0";
  }
  else {
    sensorWert0 = (",");
  }

  ////////////// sensor value 1 /////////////////////////
  if (sensorValue1 >= 0 && sensorValue1 <= 9) {
    sensorWert1 = ",00";
  }
  else if (sensorValue1 >= 10 && sensorValue1 <= 99) {
    sensorWert1 = ",0";
  }
  else {
    sensorWert1 = (",");
  }
}

void detectJoystickChanges() {

  buttonValue = !digitalRead(buttonPin);
  if (oldSensorValue0 != sensorValue0) {
    // For a weird reason String message, doesnt get printed with Attiny 
    btSerial.print(message0);
    btSerial.print(sensorWert0);
    btSerial.println(sensorValue0);

    //The string addition, doesnt work with Attiny
    //btSerial.println(str0);
    //btSerial.println(message0 + sensorWert0 + sensorValue0);

    oldSensorValue0 = sensorValue0;
  }

  else if    (oldSensorValue1 != sensorValue1) {
    // For a weird reason String message, doesnt get printed with Attiny 
    btSerial.print(message1);
    btSerial.print(sensorWert1);
    btSerial.println(sensorValue1);
    

    //The string addition, doesnt work with Attiny
    //btSerial.println(str1);
    //btSerial.println(message1 + sensorWert1 + sensorValue1);

    oldSensorValue1 = sensorValue1;
  }


  else if (oldButtonValue != buttonValue) {
    if (buttonValue) {
      btSerial.println("KEY,001"); //buttton pressed
    }
    else btSerial.println("KEY,000"); //buttton released
    oldButtonValue = buttonValue;
  }
}

Suspect you're running out of memory - the T85 doesn't have much, and you're using the String class, which is notorious for causing memory problems because of the dynamic memory allocation. And you're not using F() macro when you can, so you're throwing ram away storing string constants.

Use c strings and strcat(), or consecutive print statements (the latter looks like probably a better way considering what you're doing) to combine strings and use F() macro where you can.

Generally speaking, you should avoid the String class like the plague - particularly on low memory chips. It's best to not use it at all, because it leads to problems like, well, what you're experiencing. I think it's failing to allocate memory to store the combined String.

Just doing the F() macro when you're printing a static string literal would make a huge difference, and might even give you enough free memory that your use of String will work as is. You're wasting almost half your RAM storing strings whose values will never change!

DrAzzy you are a real doctor, who cured my program!! Thank you so much :-)

I was unaware of the F() macro which saved more than half of the dynamic memory of my program and now is working like a charm!

I have to admit I was always considering the program storage page and not the dynamic memory.

There two Arduino things you should avoid

  1. delay()
  2. String class

That’s like the dark side of the friendly Arduino…