How do I print numbers to the serial monitor using attiny85?

For lack of a uart, the digistump wiki suggests using a software library called DigiKeyboard to print to the serial monitor… fine but it won’t print anything but text. I toiled over the fix_fft library to get it working on the 85 and finally got it to compile and upload but now I can’t check if it’s actually working because I can’t print the array to the monitor. Can anyone give me a snippet of example code that would do this for the attiny85? Much appreciated!

http://www.ernstc.dk/arduino/tinycom.html

But I looked at this already and none of it works for the monitor - only transmitting serial data externally. I'm sure you're going to tell me I'm wrong and I missed something but since I've been staring at this and other similar pages for hours I hope you'll just fast-forward me to the answer.

Perhaps I should clarify that I'm looking for a way to print numbers to the monitor directly through the board's usb and not via extra wiring or purchased accessories like usb converters.

DigiKeyboard seems to inherit from the Print class. Why would it not print numbers? Can you show some demonstration code? Not your whole FFT, just a small example which compiles and demonstrates the problem.

#include "fix_fft.h"
#include "DigiKeyboard.h"

char im[128];
char data[128];
byte factor;
byte a;

void setup() {
  
  pinMode(1, OUTPUT);
  
  }

void loop(){

  delay(factor);
  digitalWrite(1, !digitalRead(1));
  int static i = 0;
  static long tt;
  int val;
  
   if (millis() > tt){
	if (i < 128){
	  val = analogRead(5);
	  data[i] = val / 4 - 128;
	  im[i] = 0;
	  i++;  
	  
	}
	else{
	  //this could be done with the fix_fftr function without the im array.
	  fix_fft(data,im,7,0);
	  // I am only interessted in the absolute value of the transformation
	  for (i=0; i< 64;i++){
	     data[i] = sqrt(data[i] * data[i] + im[i] * im[i]);
	  }
	  
	  //do something with the data values 1..64 and ignore im
//	  show_big_bars(data,0);
  

	}

     factor = data[60]; 
     for(a=0; a<64; a++) {
      
      String tempy = String(data[a]);
      DigiKeyboard.print(tempy);
      DigiKeyboard.print(",");

    }

    DigiKeyboard.println("");
    
    tt = millis();
   }
}
      String tempy = String(data[a]);

Why?

CodingBadly - Because I couldn’t get it to print numbers so I figured the numbers had to be printed as literals. (this ultimately ended up being a false premise)

I’ve been playing with the code and I managed to get it to print more or less correctly by blindly excising code snippets from other working examples. I prefer to understand my problems first but sometimes the brute force method is necessary when the clock strikes 1AM and you start hallucinating. The problem now is, the printing pattern is rather bizarre for 2 reasons:

  1. Most of the output is negative, which doesn’t make sense to me. I followed the FFT instructions to divide the ADC value by 4 so it will fit into an 8 bit space and then subtract 128 but I don’t understand the 128 part. Subtracting that is probably why my values are negative I’m guessing.

  2. Every time the program loops and another FFT is performed, the output includes 1 more non-zero number. For example, the first FFT array that prints will look like -128,0,0,0,0… etc. and then the next line will look like -128, -127, 0,0,0,0,0,0… etc. and the next line, -128, -127, -128, 0,0,0,0… etc.
    I find it hard to believe that these are actual results. Rather, I think the program is progressively printing more of the results each time but ignoring most of it at the beginning for some reason.

I’m hoping to get the code to the point where it prints non-negative values and prints all of them the first time so I can see how the magnitudes fluctuate with the input. Right now I’m just reading noise in the air but even that should look more interesting than a -128 in the first frequency bucket.

#include "fix_fft.h"
#include "DigiKeyboard.h"

char im[128];
char data[128];
byte factor;
byte a;

void setup() {
  
  pinMode(1, OUTPUT);
  DigiKeyboard.delay(3000);
  
  }

void loop(){

  delay(factor);
  digitalWrite(1, !digitalRead(1));
  int static i = 0;
  static long tt;
  int val;
  
   if (millis() > tt){
 if (i < 128){
  val = analogRead(1);
  data[i] = val / 4 - 128;
  im[i] = 0;
    delay(10);
  i++;  
  
 }
 else{
  //this could be done with the fix_fftr function without the im array.
  fix_fft(data,im,7,0);
  // I am only interessted in the absolute value of the transformation
  for (i=0; i< 64;i++){
     data[i] = sqrt(data[i] * data[i] + im[i] * im[i]);
  }
  
  //do something with the data values 1..64 and ignore im
//  show_big_bars(data,0);
  

 }
     
     factor = data[60]; 
     for(a=0; a<64; a++) {
      DigiKeyboard.delay(10);
      DigiKeyboard.print(data[a], DEC);
      DigiKeyboard.print(",");

    }

    DigiKeyboard.println("");
    
    tt = millis();
   }
}

Good God! How long have I been fighting with this horrible code with gross errors staring me in the face? This is why I don’t like copying shit off the net. You get a seemingly intelligent poster saying he got FFT working on a Tiny and he posts his code, I copy it, it compiles but doesn’t work and I spend the next 4 hours trying to figure out why, only to find that the FFT isn’t even running because the starting array isn’t even filling properly and the FFT is never called (it was in an else block that never satisfies)! As soon as I saw that I made a few minor corrections and things are making much more sense in the monitor output:

#include "fix_fft.h"
#include "DigiKeyboard.h"

char im[128];
char data[128];
byte factor;
byte a;

void setup() {
  
  pinMode(1, OUTPUT);
  DigiKeyboard.delay(3000);
  
  }

void loop(){

  delay(factor);
  digitalWrite(1, !digitalRead(1));
  int static i = 0;
  static long tt;
  
  if (millis() > tt){
	while(i < 128){
	  data[i] = analogRead(1);
	  im[i] = 0;
	  i++;    
	}
  i = 0;
  while(i < 128) {

    data[i] = data[i]/4-128;
    i++;
    
  }
  
 

	  //this could be done with the fix_fftr function without the im array.
	  fix_fft(data,im,7,0);
	  // I am only interessted in the absolute value of the transformation
	  for (i=0; i< 64;i++){
	     data[i] = sqrt(data[i] * data[i] + im[i] * im[i]);
	  }
	  
	  //do something with the data values 1..64 and ignore im
//	  show_big_bars(data,0);
  

	
     
     factor = data[60]; 
     for(a=0; a<64; a++) {
      DigiKeyboard.delay(10);
      DigiKeyboard.print(data[a], DEC);
      DigiKeyboard.print(",");

    }

    DigiKeyboard.println("");
    
    tt = millis();
   }
}

I have only myself to blame… the errors were pretty obvious if I only bothered to look at them instead of trying to reverse-engineer the header file.

So... because I've been a pain and other people will be disinclined to read this thread unless there's something of value in it, here are my lessons learned:

  1. Fix_FFT is not trivial to set up. Much of the code is incompatible with the current compiler and the examples that are available on the net are broken until you take out the un-referenced variables and fix the variable type declarations so they are recognized by the compiler.

  2. I haven't seen a working example of Fix_FFT that functions on a Tiny85. The most complete example was the basis for my code but it had massive errors in it. It only fills out 1 data array cell at a time each loop instead of populating the whole thing as it should. It never calls the FFT function because it checks if a variable declared as 0 is less than 128 (wtf?!). Also it's not very good at doing FFT because the ADC read loop should be pretty bare to give the best conversion speed but it's cluttered with garbage that kills time and renders the FFT useless.

I will attempt to clean this sketch up and optimize it further and then I will post it here so that hopefully it can be used as a new master example file for anyone wanting to run FFT on a Tiny. Perhaps this seems like an obscure application to start with but actually it's a pretty damn good idea when you think about it. I mean the Tiny85 is actually faster than the ATMega328 by half a MHz and its small footprint makes it ideal for FFT because once you run FFT on a processor you ain't doing much else with it... this is really processor/memory intensive so why waste money and board space and pins that you will never use? The tiny is a perfect high-powered, throw-away unit that does only 1 thing and does it well. If you use the TWI communication and set it up as a slave, you can basically make it a dedicated co-processor to do FFT on a signal and only communicate the important results back to the master on a need-to-know basis so the master can use its I/O and processor time to do more elaborate tasks. My 2c