Writing code for an analogue tachometer powered by Attiny85

Hello, I'm trying to write some code for an Attiny85 to run an analogue tachometer whose range of movement is not linear. I have (what I believe) are all of the steps that i need to have the Attiny85 operate the gauge properly, but my attempts of getting code to compile are not working.
1: Load lookup tables into ram/sram
2: Measure the distance in the incoming pulse frequency
3: Convert the distance to rpm (Distance being time)
4: Look for the rpm value in a table, interpolate if not there
5: Store interpolated rpm value
6: Measure incoming voltage
7: Interpolate voltage data to give the right milli amp modifier
8: Modify interpolated rpm value with modifier
9: Output the frequency while looping back to redo the calculation
The plan is to test all of the code and make lookup tables off of an Uno.
If you have suggestions on how to write the code or lessons on C++, i would really appreciate it. This is my first real coding project, and the only experience that I've had with coding so far is drawing in java script.


(The schematic is missing a flyback diode, it will be added)

Do you have a representative set of values to graph?

What error do you see?

Post your code here using the <CODE> button in the reply box.

These are the values that made the needle move though it's range
9v, 1500 ohm = 2000 rpm
9v, 1000 ohm = 3100 rpm
9v, 667 ohm = 4225 rpm
9v, 390 ohm = 6650 rpm
9v, 330 ohm = 7600 rpm
The compiling works up until the interpolators, just after the unsigned long rpm_look_up = micros() - start; . I copy pasted the interpolators, so I don't know how they really work.

#define frequency_output MISO
#define volt_sense PCINT3
#define coil_neg SCK

void setup() {
  // put your setup code here, to run once:
  pinMode(frequency_output, OUTPUT);
  pinMode(volt_sense, INPUT);
  pinMode(coil_neg, INPUT);
  int default_frequency(0);
  int volt_mod(0);
  unsigned long pulse_time(0);
  digitalWrite(frequency_output, LOW);
}

void loop() {
  // put your main code here, to run repeatedly:
  // Voltage measuring
  while ((SCK) == 0)
    ;  //wait for High on Pin2 of PORTB
  unsigned long start = micros();
  while (SCK)
    ;  //wait for Low
  while ((SCK) == 0)
    ;  //wait for High
  unsigned long rpm_look_up = micros() - start;
  // Start of rpm interpolation
  //Look up table for RPM to frequency output.
  rpm_look_up; c[5] = {
    { 300, 10.02 },
    { 700, 89.542 },
    { 800, 126.452 },
    { 900, 171.453 },
    { 1500, 225.123 }
  };
  double default_frequency(rpm_look_up * c, double x, int n)  //Default_frequency is output #
  {
    int i;
    for (i = 0; i < n - 1; i++) {
      if (c[i].x <= x && c[i + 1].x >= x) {
        double diffx = x - c[i].x;
        double diffn = c[i + 1].x - c[i].x;
        return c[i].y + (c[i + 1].y - c[i].y) * diffx / diffn;
      }
    }
    return 0;  // Not in Range
  }
  int main(int argc, char** argv) {
    double y = Default_frequency(c, 850, 5);
  }

  //Volt sensing
  int analogIn = analogRead(volt_sense);  // Read analog voltage on pin PCINT3
  // voltage interpolation
  typedef volt_sense {
    double x;
    double y;
  }
  volt_to_mod;  //Look up table for RPM to frequency output.
  volt_to_mod c[2] = {
    { 0, 0 },
    { 5, 1 }
  };
  double volt_mod(volt_to_mod * c, double x, int n)  //volt_mod is output variable
  {
    int i;
    for (i = 0; i < n - 1; i++) {
      if (c[i].x <= x && c[i + 1].x >= x) {
        double diffx = x - c[i].x;
        double diffn = c[i + 1].x - c[i].x;
        return c[i].y + (c[i + 1].y - c[i].y) * diffx / diffn;
      }
    }
    return 0;  // Not in Range
  }
  int main(int argc, char** argv) {
    double y = volt_mod(c, 850, 5);
  }
  //Multiplication
  int frequency_output = volt_mod * default_frequency;
  //Output
  analogWrite(frequency_output);  // Output PWM
}

These are all of the errors.

C:\Users\User\Documents\Arduino\Tachometer_project_V1.3\Tachometer_project_V1.3.ino: In function 'void loop()':
C:\Users\User\Documents\Arduino\Tachometer_project_V1.3\Tachometer_project_V1.3.ino:29:16: error: 'c' was not declared in this scope
   rpm_look_up; c[5] = {
                ^
C:\Users\User\Documents\Arduino\Tachometer_project_V1.3\Tachometer_project_V1.3.ino:36:45: error: expected primary-expression before 'double'
   double default_frequency(rpm_look_up * c, double x, int n)  //Default_frequency is output #
                                             ^~~~~~
C:\Users\User\Documents\Arduino\Tachometer_project_V1.3\Tachometer_project_V1.3.ino:36:55: error: expected primary-expression before 'int'
   double default_frequency(rpm_look_up * c, double x, int n)  //Default_frequency is output #
                                                       ^~~
C:\Users\User\Documents\Arduino\Tachometer_project_V1.3\Tachometer_project_V1.3.ino:48:35: error: a function-definition is not allowed here before '{' token
   int main(int argc, char** argv) {
                                   ^
In file included from c:\users\user\appdata\local\arduino15\packages\arduino\tools\avr-gcc\7.3.0-atmel3.6.1-arduino7\avr\include\avr\io.h:272:0,
                 from c:\users\user\appdata\local\arduino15\packages\arduino\tools\avr-gcc\7.3.0-atmel3.6.1-arduino7\avr\include\avr\pgmspace.h:90,
                 from C:\Users\User\AppData\Local\Arduino15\packages\arduino\hardware\avr\1.8.7\cores\arduino/Arduino.h:28,
                 from C:\Users\User\AppData\Local\arduino\sketches\CAE7CE3AF2F45DE198D58CFB12EC7FF4\sketch\Tachometer_project_V1.3.ino.cpp:1:
C:\Users\User\Documents\Arduino\Tachometer_project_V1.3\Tachometer_project_V1.3.ino:2:20: error: expected unqualified-id before numeric constant
 #define volt_sense PCINT3
                    ^
C:\Users\User\Documents\Arduino\Tachometer_project_V1.3\Tachometer_project_V1.3.ino:55:11: note: in expansion of macro 'volt_sense'
   typedef volt_sense {
           ^~~~~~~~~~
C:\Users\User\Documents\Arduino\Tachometer_project_V1.3\Tachometer_project_V1.3.ino:59:3: error: 'volt_to_mod' was not declared in this scope
   volt_to_mod;  //Look up table for RPM to frequency output.
   ^~~~~~~~~~~
C:\Users\User\Documents\Arduino\Tachometer_project_V1.3\Tachometer_project_V1.3.ino:59:3: note: suggested alternative: 'port_to_mode_PGM'
   volt_to_mod;  //Look up table for RPM to frequency output.
   ^~~~~~~~~~~
   port_to_mode_PGM
C:\Users\User\Documents\Arduino\Tachometer_project_V1.3\Tachometer_project_V1.3.ino:60:15: error: expected ';' before 'c'
   volt_to_mod c[2] = {
               ^
C:\Users\User\Documents\Arduino\Tachometer_project_V1.3\Tachometer_project_V1.3.ino:64:36: error: expected primary-expression before 'double'
   double volt_mod(volt_to_mod * c, double x, int n)  //volt_mod is output variable
                                    ^~~~~~
C:\Users\User\Documents\Arduino\Tachometer_project_V1.3\Tachometer_project_V1.3.ino:64:46: error: expected primary-expression before 'int'
   double volt_mod(volt_to_mod * c, double x, int n)  //volt_mod is output variable
                                              ^~~
C:\Users\User\Documents\Arduino\Tachometer_project_V1.3\Tachometer_project_V1.3.ino:76:35: error: a function-definition is not allowed here before '{' token
   int main(int argc, char** argv) {
                                   ^
C:\Users\User\Documents\Arduino\Tachometer_project_V1.3\Tachometer_project_V1.3.ino:82:31: error: too few arguments to function 'void analogWrite(uint8_t, int)'
   analogWrite(frequency_output);  // Output PWM
                               ^
In file included from C:\Users\User\AppData\Local\arduino\sketches\CAE7CE3AF2F45DE198D58CFB12EC7FF4\sketch\Tachometer_project_V1.3.ino.cpp:1:0:
C:\Users\User\AppData\Local\Arduino15\packages\arduino\hardware\avr\1.8.7\cores\arduino/Arduino.h:139:6: note: declared here
 void analogWrite(uint8_t pin, int val);
      ^~~~~~~~~~~
exit status 1

Compilation error: 'c' was not declared in this scope

Let's fix one then you will have an idea. The error is telling you it does not have variable c declared. You need to move it before the loop function. Now do that for the many others like it. Some will be more tricky but just fix one at a time. And where did you get the idea of main?

@stuntman225

Good Project! By practicing its implementation, there are a lot of things that could be learnt. Now, follow SSS (Start with Small Step) Strategy to complete the project.

A: Begin with the most easiest Step-6 out-of-9 steps which is:
6: Measure incoming voltage (VBATT : 12V Battery Voltage, I assume)

Procedures:
1. (a) Get an Arduino UNO R3, two fresh ATtiny85 chips, a breadboard, 12V Battery, and few male-male jumpers. UNO R3 will be used to program the ATtiny85.

or
Collect the following Digispark ATtiny85 Dev Board. It has onboard Atint85 MCU which can be dieclt programmed from the Arduino IDE. Also, download datasheet of Attiny85.



2. Tell me if you are going to use UNO R3+ATtiny85 or Digispark ATtiny85 Dev Baord. Depending on your answer, I will let you know the next step.

...and remove the semicolon between the type "rpm_look_up" and array name:

//Look up table for RPM to frequency output.
rpm_look_up c[5] = {
    { 300, 10.02 },
...

(By the way, this isn't the only change needed, the sketch looks like a "mix" of source code fragments with function definitions inside the loop() function...)


7805 datasheet:

Use ceramic capacitors, which have a better high frequency response. Also add 100nF across ATtiny85 power pins

isn't the first step to determine how to drive the Tach to produce the desired meter indication? wouldn't that be a relatively simple piece of code using either the serial monitor as the input as the desired tach value or read it from a pot.

someone said as a professional they controlled a tach using a stepper motor

Your diagram shows polarized capacitors, so they must be either electrolytic or tantalum, certainly not ceramic.

In any case it will work perfectly fine with the 10uF

Hi Jim, I'm not sure which diagram you think is mine. One is from the OP and the other is from the data sheet.
Let's try the TI data sheet.


What is your rationale for not using ceramic capacitors on 7805 input / output? I'm not saying you're wrong. It's just that I've always (for 30 ish years) thought the datasheet suggests using them.

By "your diagram" I mean the one you show in your post #7 with the 0.33uF and 0.1uF capacitors

It clearly shows polarized capacitors.

Good plan. Stay the UNO as long as you can!

That made me look! rpm_look_up is not a type, which is the roll it plays in that statement.

So missing is the declaration of a struct, something like

struct rpm_look_up {
  int x;
  float y;
} c[5] = {
    { 300, 10.02 },
... 

rpm_look_up is also used as a scalar variabke, a different name will be necessary there.

a7

This looks like a job for pulseIn()

  // Voltage measuring
  while ((SCK) == 0)
    ;  //wait for High on Pin2 of PORTB
  unsigned long start = micros();
  while (SCK)
    ;  //wait for Low
  while ((SCK) == 0)
    ;  //wait for High
  unsigned long rpm_look_up = micros() - start

which has the added benefit of timing out after it is evident no pulse has occurred.

https://docs.arduino.cc/language-reference/en/functions/advanced-io/pulseIn/

a7

Just wondering what VBATT means in this scenario. Is it the car battery (with the engine running) or is it a separate battery ?

If car battery, then the negative side of the battery should have been connected with the chassis of the car; but, nowhere there is such
image
sysmbol in the schematic.

I am just looking for confirmation either way, not speculation. I can speculate myself ;-)

I will be using an UNO Q + ATtiny85 to test and program. I know that the UNO Q is over kill, but it's the only working Arduino that i can borrow.

Yes, the parts to build my circuit with haven't arrived, so I was trying to tackle the majority of the code first.

It's the car battery that's connected to the alternator. For testing the setup will be connected a 12v power supply.

I've ordered electrolytic caps, if they don't work at filtering enough noise I'll order some ceramic caps.