RPM to Speedometer Help Thanks

i guess i will be using 2 arduino then since i cannot get higher frequency with 1 arduino

It should be very possible to drive both the motor and the speedo with independent high frequency pwm on the same arduino. What frequency do you exactly need to stay out of the audible range? 32K seems a bit high.

Please post your latest code, and describe the exact problems you have with it.

Are all your issues on the output side of pwm to the motor and speedo, or are there still issues with the input side involving the pot and the interrupt?

Please post info on the meter / motor you are using to display speed.

the speedo is an analog coming from my electric scooter was working when dismantled but the controller burned during a hillclimb already replaced but no controller here that control the speedo
and since the speedo didn’t have a manual for the wiring had no choice but to dismantle it and directly solder some wire

hall sensor conected to digital pin2
motor pin at 9
speedo pin at 9
both potentiometer at A0,A1 A0 is throttle, A1 is the acceleration curve adjuster

Ctrl F beta Freq if you want to activate frequency and remove the // at setfrequency

i need the speedo hert to be 16Khertz or highter
i need the Motor hertz to be 20Khertz or higher

this is the latest code

/* PWM pour moteur à courant continu avec réglage de la souplesse de conduite (2 potentiomètres).
  Version 1.4, Incroyables Expériences */
  /*its now in v1.7 from buder :D*/

#include <PWM.h>
#define MainPeriod 100


unsigned long  previousMillis = 0; // will store last time of the cycle end
volatile unsigned long duration=0; // accumulates pulse width
volatile unsigned int pulsecount=0;
volatile unsigned long previousMicros=0;

            
float THRint =0;              //THRint     requested throttle when thumb removed from throttle                                           // Initialisation du rapport cyclique réel à 0.
float ACCpot=30;              //before was (S) base Accel Initialisation              // Initialisation de la souplesse de conduite.
int THRpot=0;                 //Throttle poteniometer                                 // Initialisation du rapport cyclique demandé à 0.
int THRmem=0;                 //THRmem                                                // Initialisation de la mémoire du rapport cyclique demandé.
int Safety=7000; // default 70 safety if the throttle  is floored too fast increase number to disable/lower the safety  sensibility (at 700 is clearly disabled)
int32_t frequency= 20000; 
int32_t frequency2= 20000;
int Motor = 9;  //THRout is throttle to connect to transistor/driver/led/ebike controller
int SpeedoPin = 3; //Speedo Pin

void setup()                  //setup loop                                           // Boucle d'initialisation.
{
    Serial.begin(9600);
      attachInterrupt(0, myinthandler, RISING);
      InitTimersSafe(); 
    pinMode(Motor, OUTPUT);  // pin5 set as THRout  (throttle out)      

     pinMode(SpeedoPin, OUTPUT);  // pin10 set as to speedo mosfet      
}


void loop() {           // main loop  // Boucle principale

int MapTHRint = map(THRint, 110, 1200, -22, 340);
int insideTHR = constrain(MapTHRint,0,255);


  

  THRpot=analogRead(A0);               //throttle pot reading                                                      // Lecture du rapport cyclique demandé.
  ACCpot=analogRead(A1);               //acceleration threshold pot reading                                        // Lecture de la souplesse de conduite demandée.

  if(THRpot>THRmem+Safety){            //check for  brutale THRpot request (aka flooring the throttle too fast)    // Vérification d'une accélération trop brutale (d'origine volontaire ou non).
    digitalWrite(Motor,LOW);          //imediatly stop if THRout above Safety                                     // Arrêt immédiat du moteur.
    while(THRpot>Safety){              //waiting for THRpot to be lower than safety to restart                     // Attente d'un rapport cyclique très faible pour redémarrer.
      THRpot=analogRead(0);            // Lecture continue du rapport cyclique demandé.
    }
  }
  THRmem=THRpot; // Mémorisation du rapport cyclique demandé.

  if(THRpot>THRint){ //checking for throttle increase                                        // Vérification de la croissance du rapport cyclique demandé.
    delay(20); // Délai responsable de la souplesse de conduite.
    THRint=THRint+ACCpot/20+2; // Calibrage empirique de la souplesse de conduite.
  }
   if(THRpot<THRint){ //checking if you removed your thumb from the throttle                  // Vérification de la décroissance du rapport cyclique demandé.
    THRint=THRpot; //stop power being sent if above true(aka thumb removed from throttle)    // Diminution immédiate du rapport cyclique réel le cas échéant.
  }

 //Beta FREQ 
//    SetPinFrequencySafe(Motor, frequency);   //set frequency and speed 
//   SetPinFrequencySafe(SpeedoPin, frequency2);   //set frequency and speed 
 

        
  unsigned long currentMillis = millis();


 if (currentMillis - previousMillis >= MainPeriod)
  {
    previousMillis = currentMillis;   
    // need to bufferize to avoid glitches

    noInterrupts();
    unsigned long _duration = duration;
    unsigned long _pulsecount = pulsecount;
    duration = 0; // clear counters
    pulsecount = 0;
    interrupts();

    float Freq = 1e6 / float(_duration);    //Duration is in uSecond so it is 1e6 / T

    Freq *= _pulsecount; // calculate F
    // output time and frequency data to RS232
    Serial.print(" Frequency: ");
    Serial.print(Freq);
    Serial.print("Hz ");
    int RPMmulti = Freq*30;   //converter from 1 magnet to 2 magnet  1 magnet is 60
    Serial.print(" RPM: ");
    Serial.print(RPMmulti); 



int MapRPMmulti = map(RPMmulti, 0, 3000, 0, 255);
int Speedo = constrain(MapRPMmulti,0,255);




    Serial.print(" Speedo: ");
    Serial.println(Speedo);
      //  analogWrite(10,Speedo);
  pwmWrite(SpeedoPin,Speedo);
  pwmWrite(Motor, insideTHR); 
 
}


}



void myinthandler() // interrupt handler
{
  unsigned long currentMicros = micros();
  duration += currentMicros - previousMicros;
  previousMicros = currentMicros;
  pulsecount++;
}

when i live activate frequency to deactivate wacth the rpm in the window

and i prety much gave up todo it on my own seem what i am asking is too advanced for what i know

You are running the pwm at a constant frequency of 20KHz, and the set Frequency commands belong in setup() and not loop().

//Beta FREQ
//    SetPinFrequencySafe(Motor, frequency);   //set frequency and speed
//   SetPinFrequencySafe(SpeedoPin, frequency2);   //set frequency and

Please report back what this move to setup does.

If the program does not work properly, the next think I would do is to move the section with the analogRead() of the different pots into a periodic timer and not every pass through loop(). Very frequent analogReads() can create problems as they can block other interrupts. Pots are adjusted at human speed, not Arduino speed.

I think you are confusing PWM with a variable frequency square wave, try feeding your "Speedo" with pulses from the Tone function.

tone(pin, 16000UL);

both solution dosent work
moving the setfreq to setup create same problem false reading all over the place of the rpm

if i use tone function the speedo stop working i hear noise from it but not moving
i made sure to change the pin 3 to 10 but dosent work or i dont know how to use it

Edit1: i need a variable duty cycle at a fixed frequency of 20Khertz

moving the setfreq to setup create same problem false reading all over the place of the rpm. i need a variable duty cycle at a fixed frequency of 20Khertz

I do not understand the interaction of the rpm interrupt on pin2 and the pwm outputs on pins 3 and 9. I do know that for a fixed frequency the correct place for timer setup is in setup().

First thing is to make sure that pin2 is not floating in any way. I would explicitly set the pinMode of the interrupt pin to INPUT_PULLUP. Is there an external pullup on the Hall Sensor? Most of the sensors are open collector output and require pullups to work properly.

Lets work forward from the point where the frequency is fixed in setup(). This is absolutely the correct place to do it.

  1. Is there some frequency less than 20KHz which does not create the false readings of the rpm?

  2. If you forget about the PWM.h and the attempts to get 20KHZ output but simply use analogWrite() for both the motor and the speedo does the program work properly except for audible noise?

#1using analogWrite give proper reading but disabling give same result as using analogWrite (give proper reading)

//Beta FREQ 
//   SetPinFrequencySafe(Motor, frequency);   //set frequency and speed 
//   SetPinFrequencySafe(SpeedoPin, frequency2);   //set frequency and speed

#2 no idea how to setup highter freq without the library since that is its reason to be loaded

image here is the hall sensor wiring

if i try to use the hall sensor without capacitor its a no-no never work nomater the wiring i tried like 10 way to wire this up and some sketch

unless its the pullup that never worked for me

this is the calculation from hertz to rpm

    int RPMmulti = Freq*30;   Hertz to RPM 60 60/(magnet number)= your rpm. i use 2 magnet so 30
    Serial.print(" RPM: ");
    Serial.print(RPMmulti); 



int MapRPMmulti = map(RPMmulti, 0, 3000, 0, 255);
int Speedo = constrain(MapRPMmulti,0,255);

  pwmWrite(SpeedoPin,Speedo);
  pwmWrite(Motor, insideTHR);

latest full code

/* PWM pour moteur à courant continu avec réglage de la souplesse de conduite (2 potentiomètres).
  Version 1.4, Incroyables Expériences */
  /*its now in v1.7 from buder :D*/

#include <PWM.h>
#define MainPeriod 100


unsigned long  previousMillis = 0; // will store last time of the cycle end
volatile unsigned long duration=0; // accumulates pulse width
volatile unsigned int pulsecount=0;
volatile unsigned long previousMicros=0;

            
float THRint =0;              //THRint     requested throttle when thumb removed from throttle                                           // Initialisation du rapport cyclique réel à 0.
float ACCpot=30;              //before was (S) base Accel Initialisation              // Initialisation de la souplesse de conduite.
int THRpot=0;                 //Throttle poteniometer                                 // Initialisation du rapport cyclique demandé à 0.
int THRmem=0;                 //THRmem                                                // Initialisation de la mémoire du rapport cyclique demandé.
int Safety=7000; // default 70 safety if the throttle  is floored too fast increase number to disable/lower the safety  sensibility (at 700 is clearly disabled)
int32_t frequency= 20000; 
int32_t frequency2= 20000;
int Motor = 9;  //THRout is throttle to connect to transistor/driver/led/ebike controller
int SpeedoPin = 3; //Speedo Pin
int delayVar=20;//delay for acceleration speed to be used with rpm later
void setup()                  //setup loop                                           // Boucle d'initialisation.
{
    Serial.begin(9600);
      attachInterrupt(0, myinthandler, RISING);
      InitTimersSafe(); 
    pinMode(Motor, OUTPUT);  // pin5 set as THRout  (throttle out)      

     pinMode(SpeedoPin, OUTPUT);  // pin10 set as to speedo mosfet   

         //Beta FREQ 
//   SetPinFrequencySafe(Motor, frequency);   //set frequency and speed 
//   SetPinFrequencySafe(SpeedoPin, frequency2);   //set frequency and speed 
 
}


void loop() {           // main loop  // Boucle principale

int MapTHRint = map(THRint, 110, 1200, -22, 340);
int insideTHR = constrain(MapTHRint,0,255);


  

  THRpot=analogRead(A0);               //throttle pot reading                                                      // Lecture du rapport cyclique demandé.
  ACCpot=analogRead(A1);               //acceleration threshold pot reading                                        // Lecture de la souplesse de conduite demandée.

  if(THRpot>THRmem+Safety){            //check for  brutale THRpot request (aka flooring the throttle too fast)    // Vérification d'une accélération trop brutale (d'origine volontaire ou non).
    digitalWrite(Motor,LOW);          //imediatly stop if THRout above Safety                                     // Arrêt immédiat du moteur.
    while(THRpot>Safety){              //waiting for THRpot to be lower than safety to restart                     // Attente d'un rapport cyclique très faible pour redémarrer.
      THRpot=analogRead(0);            // Lecture continue du rapport cyclique demandé.
    }
  }
  THRmem=THRpot; // Mémorisation du rapport cyclique demandé.

  if(THRpot>THRint){ //checking for throttle increase   
  // Vérification de la croissance du rapport cyclique demandé.
delay(delayVar);//to be used later its 20
    
 //   delay(20); // Délai responsable de la souplesse de conduite.
    THRint=THRint+ACCpot/20+2; // Calibrage empirique de la souplesse de conduite.
  }
   if(THRpot<THRint){ //checking if you removed your thumb from the throttle                  // Vérification de la décroissance du rapport cyclique demandé.
    THRint=THRpot; //stop power being sent if above true(aka thumb removed from throttle)    // Diminution immédiate du rapport cyclique réel le cas échéant.
  }



        
  unsigned long currentMillis = millis();


 if (currentMillis - previousMillis >= MainPeriod)
  {
    previousMillis = currentMillis;   
    // need to bufferize to avoid glitches

    noInterrupts();
    unsigned long _duration = duration;
    unsigned long _pulsecount = pulsecount;
    duration = 0; // clear counters
    pulsecount = 0;
    interrupts();

    float Freq = 1e6 / float(_duration);    //Duration is in uSecond so it is 1e6 / T

    Freq *= _pulsecount; // calculate F
    // output time and frequency data to RS232
    Serial.print(" Frequency: ");
    Serial.print(Freq);
    Serial.print("Hz ");
    
    int RPMmulti = Freq*30;   Hertz to RPM 60 60/(magnet number)= your rpm. i use 2 magnet so 30
    Serial.print(" RPM: ");
    Serial.print(RPMmulti); 



int MapRPMmulti = map(RPMmulti, 0, 3000, 0, 255);
int Speedo = constrain(MapRPMmulti,0,255);




    Serial.print(" Speedo: ");
    Serial.println(Speedo);
      //  analogWrite(10,Speedo);
  pwmWrite(SpeedoPin,Speedo);
  pwmWrite(Motor, insideTHR); 
 
}


}



void myinthandler() // interrupt handler
{
  unsigned long currentMicros = micros();
  duration += currentMicros - previousMicros;
  previousMicros = currentMicros;
  pulsecount++;
}

The Hall sensor setup looks correct.

#1using analogWrite give proper reading but disabling give same result as using analogWrite (give proper reading)

I do not understand what is happening, but I think that the problem is with PWM.h and some interaction with the interrupt.

Here is a sketch which eliminates that library and sets up Timer1 directly. It brings both outputs back to Timer1. Pin9 is output for the motor, and pin 10 is output for the speedo.
If there is an issue, we can take the speedo back to Timer2.

Because of how the Timer is set up for 20KHz, the duty cycle values are between 0 and 99 and not 0-255. I have made the timer setup highly commented so you can see what I have done.

#define MainPeriod 100

unsigned long  previousMillis = 0; // will store last time of the cycle end
volatile unsigned long duration = 0; // accumulates pulse width
volatile unsigned int pulsecount = 0;
volatile unsigned long previousMicros = 0;

float THRint = 0;             //THRint     requested throttle when thumb removed from throttle                                           // Initialisation du rapport cyclique réel à 0.
float ACCpot = 30;            //before was (S) base Accel Initialisation              // Initialisation de la souplesse de conduite.
int THRpot = 0;               //Throttle poteniometer                                 // Initialisation du rapport cyclique demandé à 0.
int THRmem = 0;               //THRmem                                                // Initialisation de la mémoire du rapport cyclique demandé.
int Safety = 7000; // default 70 safety if the throttle  is floored too fast increase number to disable/lower the safety  sensibility (at 700 is clearly disabled)
int Motor = 9; //THRout is throttle to connect to transistor/driver/led/ebike controller
int SpeedoPin = 10;//Speedo Pin
int delayVar = 20; //delay for acceleration speed to be used with rpm later

void setup() //setup loop                                           // Boucle d'initialisation.
{
  Serial.begin(9600);
  attachInterrupt(0, myinthandler, RISING);
  setupTimer1_20Khz();
  pinMode(Motor, OUTPUT);  // pin9 set as THRout drives motor
  pinMode(SpeedoPin, OUTPUT);  // pin10 set as to speedo mosfet
  digitalWrite(Motor,LOW);
  digitalWrite(SpeedoPin, LOW);
}

void loop() {
  int MapTHRint = map(THRint, 110, 1200, -22, 340);
  //int insideTHR = constrain(MapTHRint, 0, 255);
  int insideTHR = constrain(MapTHRint, 0, 99);
  THRpot = analogRead(A0);             //throttle pot reading                                                      // Lecture du rapport cyclique demandé.
  ACCpot = analogRead(A1);             //acceleration threshold pot reading                                        // Lecture de la souplesse de conduite demandée.

  if (THRpot > THRmem + Safety) {      //check for  brutale THRpot request (aka flooring the throttle too fast)    // Vérification d'une accélération trop brutale (d'origine volontaire ou non).
    digitalWrite(Motor, LOW);         //imediatly stop if THRout above Safety                                     // Arrêt immédiat du moteur.
    while (THRpot > Safety) {          //waiting for THRpot to be lower than safety to restart                     // Attente d'un rapport cyclique très faible pour redémarrer.
      THRpot = analogRead(0);          // Lecture continue du rapport cyclique demandé.
    }
  }
  THRmem = THRpot; // Mémorisation du rapport cyclique demandé.

  if (THRpot > THRint) { //checking for throttle increase
    // Vérification de la croissance du rapport cyclique demandé.
    delay(delayVar);//to be used later its 20
    //   delay(20); // Délai responsable de la souplesse de conduite.
    THRint = THRint + ACCpot / 20 + 2; // Calibrage empirique de la souplesse de conduite.
  }
  if (THRpot < THRint) { //checking if you removed your thumb from the throttle                  // Vérification de la décroissance du rapport cyclique demandé.
    THRint = THRpot; //stop power being sent if above true(aka thumb removed from throttle)    // Diminution immédiate du rapport cyclique réel le cas échéant.
  }

  unsigned long currentMillis = millis();
  if (currentMillis - previousMillis >= MainPeriod)
  {
    previousMillis = currentMillis;
    // need to bufferize to avoid glitches
    noInterrupts();
    unsigned long _duration = duration;
    unsigned long _pulsecount = pulsecount;
    duration = 0; // clear counters
    pulsecount = 0;
    interrupts();

    float Freq = 1e6 / float(_duration);    //Duration is in uSecond so it is 1e6 / T

    Freq *= _pulsecount; // calculate F
    Serial.print(" Frequency: ");
    Serial.print(Freq);
    Serial.print("Hz ");

    int RPMmulti = Freq * 30; //Hertz to RPM 60 60 / (magnet number) = your rpm. i use 2 magnet so 30
    Serial.print(" RPM: ");
    Serial.print(RPMmulti);

    int Speedo = map(RPMmulti, 0, 3000, 0, 99);

    Serial.print(" Speedo: ");
    Serial.println(Speedo);
    
    if (insideTHR == 0)
      digitalWrite(Motor, LOW);
    else
      OCR1A = insideTHR;//motor on pin 9

    if (Speedo == 0)
      digitalWrite(SpeedoPin, LOW);
    else
      OCR1B = Speedo;//speedo on pin 10
    
  }
}

void myinthandler() // interrupt handler
{
  unsigned long currentMicros = micros();
  duration += currentMicros - previousMicros;
  previousMicros = currentMicros;
  pulsecount++;
}

void setupTimer1_20Khz()
{
  TCNT1  = 0;//clear Arduino pwm presets
  TCCR1A = 0;
  TCCR1B = 0;
  //set to mode 14 fast pwm to ICR1 top value
  //non inverted output on pins 9 (A) and 10 (B)
  //Clear OC1A/OC1B on Compare Match, set OC1A/OC1B at
  //BOTTOM (non-inverting mode)
  //ICR1 set frequency OCR1A and OCR1B set duty cycle
  //prescaler 8 gives .5 microseconds per timer tick
  // TCCR1A
  // Bit                 7      6      5       4     3      2      1      0
  // Bit Name          COM1A1 COM1A0 COM1B1 COM1B0 -----  ----- WGM11  WGM10
  // Initial Value       0      0      0       0     0      0      0      0
  // changed to        1      0      1       0     0      0      1      0

  TCCR1A = B10100010;

  // TCCR1B  prescaler 8 .5us/tick
  // Bit             7     6      5       4       3      2        1       0
  // Bit Name      ICNC1  ICES1 ----   WGM13    WGM12    CS12    CS11     CS10
  // Initial Value    0     0     0        0       0      0        0       0
  // changed to     0     0     0        1       1      0        1       0

  TCCR1B = B00011010;

  ICR1 = 99;   //Set Top Value, -> frequency 20 kHz with 16 MHz internal clock
  
}

no idea why but my power mosfet are not being turned on so both speedo and the fan dosent move
i tried power the fan to see if the speedo work and dosent :S
though the rpm read properly

they are power mosfet
NPN IRFZ44N motor
NPN IRFZ44N speedo

Please add these Serial prints to your sketch in the section before the setting of OCR1A and OCR1B. What values do you see for Speedo and insideTHR. If I set them to defined values in the code, I can see pwm output on pins 9 and 10 with test leds so I think the timer is set up correctly.

Another trouble shooting thing to do is replace the mosfet outputs on 9 and 10 with leds.

Serial.print(" Speedo: ");
    Serial.println(Speedo);
    Serial.print(" insideTHR: ");
    Serial.println(insideTHR);
    if (insideTHR == 0)
      digitalWrite(Motor, LOW);
    else
      OCR1A = insideTHR;//motor on pin 9

    if (Speedo == 0)
      digitalWrite(SpeedoPin, LOW);
    else
      OCR1B = Speedo;//speedo on pin 10

I think I may have made an error with this code. I'm not really set up well to test the code.

Try removing the conditional digitalWrite() commands right before the pwm duty cycle is set. I'm not clear on the issue, but I think that the digitalWrite() to the output pin when trying to ensure LOW is blocking the later OCR1X command for timer output.

//if (insideTHR == 0)
      //digitalWrite(Motor, LOW);
    //else
      OCR1A = insideTHR;//motor on pin 9

    //if (Speedo == 0)
     // digitalWrite(SpeedoPin, LOW);
   // else
      OCR1B = Speedo;//speedo on pin 10

EDIT:
Yes, I have reviewed wiring_digital.c and can see that the digitalWrite disables the timer compare match output. Code snippets from wiring_digital.c

// If the pin that support PWM output, we need to turn it off
	// before doing a digital write.
	if (timer != NOT_ON_TIMER) turnOffPWM(timer);

static void turnOffPWM(uint8_t timer)
{
	switch (timer)
	{
		#if defined(TCCR1A) && defined(COM1A1)
		case TIMER1A:   cbi(TCCR1A, COM1A1);    break;
		#endif
		#if defined(TCCR1A) && defined(COM1B1)
		case TIMER1B:   cbi(TCCR1A, COM1B1);    break;

If there is an issue with the OCR1A/OCR1B = 0 giving a short output pulse of one clock cycle, we can reset the bit for the timer output after the digitalWrite() if necessary.

The "speedo" has a motor in it?

I reviewed the code I supplied again and realize that I had some additional digitalWrites() after Timer setup in the code I supplied you, but removed from what I was testing. I apologize for being so scattered and piecemeal in my corrections. :frowning:

void setup() //setup loop                                  
{
  Serial.begin(9600);
  attachInterrupt(0, myinthandler, RISING);
  setupTimer1_20Khz();
  pinMode(Motor, OUTPUT);  // pin9 set as THRout drives motor
  pinMode(SpeedoPin, OUTPUT);  // pin10 set as to speedo mosfet
  //digitalWrite(Motor,LOW);
  //digitalWrite(SpeedoPin, LOW);
}

the speedo and insidethr print give a result of between 0 and 99
sometime the speedo recieve some 117-130

and i somehow made the motor and speedo run by giving full throttle on the throttle pot
and then reuploading the skecth while going slow speed the speedo turn on

though i hear no noise like a high frequency pwm
working potential ?

fishy

what resistor i need on LED for them to work ? i may try those later

and im lost at that static void code no idea where to put it if you want me to use it

just to say the part int MapTHRint = map(THRint, 110, 1200, -22, 340);
is not adapted for potentiometer (0-5v) it is adjusted for hall effect sensor based control (1-4v) just saying
its for use with Ebike thumb throttle controller with use hall sensor

Thanks for the help

yeah adjust the line
it give more consistant start

int MapTHRint = map(THRint, 20, 1024, 0, 255);    //backup for later   int MapTHRint = map(THRint, 110, 1200, -22, 340);

adjust the 20 to the minimum 0 may work

the code seem to want a value high enought to start but if that go negative or something the motor wont start and so need a reset and give throttleabove its needed threshold
hope that help

its probably the same for the speedo dosent allway work

aslo rpm still inconsistant specialy when i give low throttle though if i give full throttle but slow it by external force the reading seem somewhat proper

Please post the current code that you are using, and I will review it for the corrections I supplied.

and im lost at that static void code no idea where to put it if you want me to use it

That code was just documentation as to why there were problems with digitalWrite() and the Timer setup. It is not to go in the code.

aslo rpm still inconsistant specialy when i give low throttle though if i give full throttle but slow it by external force the reading seem somewhat proper

When I test the rpm section with an input from the tone function I see consistent results. I'm not certain if variations in the rpm are possibly real variations of the motor speed.

Is there any way you can simplify your code and write something with a constant throttle and values for the pot readings. Then we can sort out issues of the pwm drivers, the interrupt inputs, and the control algorithms with the varialbles.

the variation in rpm only mess up when it slow down with the pot the number skyrocket way above its own real rpm

so if we give it constant speed we wont see if it work :S but can go ahead in testing

#define MainPeriod 100

unsigned long  previousMillis = 0; // will store last time of the cycle end
volatile unsigned long duration = 0; // accumulates pulse width
volatile unsigned int pulsecount = 0;
volatile unsigned long previousMicros = 0;

float THRint = 0;             //THRint     requested throttle when thumb removed from throttle                                           // Initialisation du rapport cyclique réel à 0.
float ACCpot = 30;            //before was (S) base Accel Initialisation              // Initialisation de la souplesse de conduite.
int THRpot = 0;               //Throttle poteniometer                                 // Initialisation du rapport cyclique demandé à 0.
int THRmem = 0;               //THRmem                                                // Initialisation de la mémoire du rapport cyclique demandé.
int Safety = 7000; // default 70 safety if the throttle  is floored too fast increase number to disable/lower the safety  sensibility (at 700 is clearly disabled)
int Motor = 9; //THRout is throttle to connect to transistor/driver/led/ebike controller
int SpeedoPin = 10;//Speedo Pin
int delayVar = 20; //delay for acceleration speed to be used with rpm later

void setup() //setup loop                                           // Boucle d'initialisation.
{
  Serial.begin(9600);
  attachInterrupt(0, myinthandler, RISING);
  setupTimer1_20Khz();
  pinMode(Motor, OUTPUT);  // pin9 set as THRout drives motor
  pinMode(SpeedoPin, OUTPUT);  // pin10 set as to speedo mosfet
//  digitalWrite(Motor,LOW);
//  digitalWrite(SpeedoPin, LOW);
}

void loop() {
  int MapTHRint = map(THRint, 0, 1024, 1, 255);  //backup   int MapTHRint = map(THRint, 110, 1200, -22, 340);
  //int insideTHR = constrain(MapTHRint, 0, 255);
  int insideTHR = constrain(MapTHRint, 0, 99);
  THRpot = analogRead(A0);             //throttle pot reading                                                      // Lecture du rapport cyclique demandé.
  ACCpot = analogRead(A1);             //acceleration threshold pot reading                                        // Lecture de la souplesse de conduite demandée.

  if (THRpot > THRmem + Safety) {      //check for  brutale THRpot request (aka flooring the throttle too fast)    // Vérification d'une accélération trop brutale (d'origine volontaire ou non).
    digitalWrite(Motor, LOW);         //imediatly stop if THRout above Safety                                     // Arrêt immédiat du moteur.
    while (THRpot > Safety) {          //waiting for THRpot to be lower than safety to restart                     // Attente d'un rapport cyclique très faible pour redémarrer.
      THRpot = analogRead(0);          // Lecture continue du rapport cyclique demandé.
    }
  }
  THRmem = THRpot; // Mémorisation du rapport cyclique demandé.

  if (THRpot > THRint) { //checking for throttle increase
    // Vérification de la croissance du rapport cyclique demandé.
    delay(delayVar);//to be used later its 20
    //   delay(20); // Délai responsable de la souplesse de conduite.
    THRint = THRint + ACCpot / 20 + 2; // Calibrage empirique de la souplesse de conduite.
  }
  if (THRpot < THRint) { //checking if you removed your thumb from the throttle                  // Vérification de la décroissance du rapport cyclique demandé.
    THRint = THRpot; //stop power being sent if above true(aka thumb removed from throttle)    // Diminution immédiate du rapport cyclique réel le cas échéant.
  }

  unsigned long currentMillis = millis();
  if (currentMillis - previousMillis >= MainPeriod)
  {
    previousMillis = currentMillis;
    // need to bufferize to avoid glitches
    noInterrupts();
    unsigned long _duration = duration;
    unsigned long _pulsecount = pulsecount;
    duration = 0; // clear counters
    pulsecount = 0;
    interrupts();

    float Freq = 1e6 / float(_duration);    //Duration is in uSecond so it is 1e6 / T

    Freq *= _pulsecount; // calculate F
    Serial.print(" Frequency: ");
    Serial.print(Freq);
    Serial.print("Hz ");

    int RPMmulti = Freq * 30; //Hertz to RPM 60 60 / (magnet number) = your rpm. i use 2 magnet so 30
    Serial.print(" RPM: ");
    Serial.print(RPMmulti);

    int Speedo = map(RPMmulti, 0, 3000, 0, 99);

    Serial.print(" Speedo: ");
    Serial.println(Speedo);
   
    if (insideTHR == 0)
      digitalWrite(Motor, LOW);
    else
      OCR1A = insideTHR;//motor on pin 9

    if (Speedo == 0)
      digitalWrite(SpeedoPin, LOW);
    else
      OCR1B = Speedo;//speedo on pin 10
   
  }
}

void myinthandler() // interrupt handler
{
  unsigned long currentMicros = micros();
  duration += currentMicros - previousMicros;
  previousMicros = currentMicros;
  pulsecount++;
}

void setupTimer1_20Khz()
{
  TCNT1  = 0;//clear Arduino pwm presets
  TCCR1A = 0;
  TCCR1B = 0;
  //set to mode 14 fast pwm to ICR1 top value
  //non inverted output on pins 9 (A) and 10 (B)
  //Clear OC1A/OC1B on Compare Match, set OC1A/OC1B at
  //BOTTOM (non-inverting mode)
  //ICR1 set frequency OCR1A and OCR1B set duty cycle
  //prescaler 8 gives .5 microseconds per timer tick
  // TCCR1A
  // Bit                 7      6      5       4     3      2      1      0
  // Bit Name          COM1A1 COM1A0 COM1B1 COM1B0 -----  ----- WGM11  WGM10
  // Initial Value       0      0      0       0     0      0      0      0
  // changed to        1      0      1       0     0      0      1      0

  TCCR1A = B10100010;

  // TCCR1B  prescaler 8 .5us/tick
  // Bit             7     6      5       4       3      2        1       0
  // Bit Name      ICNC1  ICES1 ----   WGM13    WGM12    CS12    CS11     CS10
  // Initial Value    0     0     0        0       0      0        0       0
  // changed to     0     0     0        1       1      0        1       0

  TCCR1B = B00011010;

  ICR1 = 99;   //Set Top Value, -> frequency 20 kHz with 16 MHz internal clock
 
}

Because of the digitalWrite() of thr pwm pin interacting with the timer, its important to modify this section

//if (insideTHR == 0)
     // digitalWrite(Motor, LOW);
   // else
      OCR1A = insideTHR;//motor on pin 9

    //if (Speedo == 0)
    //  digitalWrite(SpeedoPin, LOW);
    //else
      OCR1B = Speedo;//speedo on pin 10

You also have this section which uses a digitalWrite(). Since Safety is set at 7000 it can never be true and executed, but when the safety settings do get used, it probably better to use the output compare

if (THRpot > THRmem + Safety) {      //check for  brutale THRpot request (aka flooring the throttle too fast)    // Vérification d'une accélération trop brutale (d'origine volontaire ou non).

  //digitalWrite(Motor, LOW);         //imediatly stop if THRout above Safety                                     

    OCR1A = 0;

 // Arrêt immédiat du moteur.
    while (THRpot > Safety) {          //waiting for THRpot to be lower than safety to restart                     // Attente d'un rapport cyclique très faible pour redémarrer.
      THRpot = analogRead(0);          // Lecture continue du rapport cyclique demandé.
    }
  }

the variation in rpm only mess up when it slow down with the pot the number skyrocket way above its own real rpm

I don't understand this. The rpm is read from an external input from a sensor on the motor. Perhaps there is real physical lag in the motor response? Can you add some serial output which shows what is going on? Or perhaps a link to a video? When you say "skyrocket" do you mean that the rpm value goes higher than what it was before you start to slow the motor down?

Can you prioritize the remaining issues to work on?

sky rocket example
+example of rpm reading properly if throttle is maxed and force is applied to the motor to slow it down

the safety value will be used when i connect this to my electric scooter for testing that safety is in the way so i gone and put absurd number to make sure it dosent get used during testing

latest code i re anranged the serialprint order because the hertz sometime jump from 2 number to 3 making hard to read xD

#define MainPeriod 100

unsigned long  previousMillis = 0; // will store last time of the cycle end
volatile unsigned long duration = 0; // accumulates pulse width
volatile unsigned int pulsecount = 0;
volatile unsigned long previousMicros = 0;

float THRint = 0;             //THRint     requested throttle when thumb removed from throttle                                           // Initialisation du rapport cyclique réel à 0.
float ACCpot = 30;            //before was (S) base Accel Initialisation              // Initialisation de la souplesse de conduite.
int THRpot = 0;               //Throttle poteniometer                                 // Initialisation du rapport cyclique demandé à 0.
int THRmem = 0;               //THRmem                                                // Initialisation de la mémoire du rapport cyclique demandé.
int Safety = 7000; // default 70 safety if the throttle  is floored too fast increase number to disable/lower the safety  sensibility (at 700 is clearly disabled)
int Motor = 9; //THRout is throttle to connect to transistor/driver/led/ebike controller
int SpeedoPin = 10;//Speedo Pin
int delayVar = 20; //delay for acceleration speed to be used with rpm later

void setup() //setup loop                                           // Boucle d'initialisation.
{
  Serial.begin(9600);
  attachInterrupt(0, myinthandler, RISING);
  setupTimer1_20Khz();
  pinMode(Motor, OUTPUT);  // pin9 set as THRout drives motor
  pinMode(SpeedoPin, OUTPUT);  // pin10 set as to speedo mosfet
//  digitalWrite(Motor,LOW);
//  digitalWrite(SpeedoPin, LOW);
}

void loop() {
  int MapTHRint = map(THRint, 0, 1024, 1, 255);  //backup   int MapTHRint = map(THRint, 110, 1200, -22, 340);
  //int insideTHR = constrain(MapTHRint, 0, 255);
  int insideTHR = constrain(MapTHRint, 0, 99);
  THRpot = analogRead(A0);             //throttle pot reading                                                      // Lecture du rapport cyclique demandé.
  ACCpot = analogRead(A1);             //acceleration threshold pot reading                                        // Lecture de la souplesse de conduite demandée.

  if (THRpot > THRmem + Safety) {      //check for  brutale THRpot request (aka flooring the throttle too fast)    // Vérification d'une accélération trop brutale (d'origine volontaire ou non).
    digitalWrite(Motor, LOW);         //imediatly stop if THRout above Safety                                     // Arrêt immédiat du moteur.
    while (THRpot > Safety) {          //waiting for THRpot to be lower than safety to restart                     // Attente d'un rapport cyclique très faible pour redémarrer.
      THRpot = analogRead(0);          // Lecture continue du rapport cyclique demandé.
    }
  }
  THRmem = THRpot; // Mémorisation du rapport cyclique demandé.

  if (THRpot > THRint) { //checking for throttle increase
    // Vérification de la croissance du rapport cyclique demandé.
    delay(delayVar);//to be used later its 20
    //   delay(20); // Délai responsable de la souplesse de conduite.
    THRint = THRint + ACCpot / 20 + 2; // Calibrage empirique de la souplesse de conduite.
  }
  if (THRpot < THRint) { //checking if you removed your thumb from the throttle                  // Vérification de la décroissance du rapport cyclique demandé.
    THRint = THRpot; //stop power being sent if above true(aka thumb removed from throttle)    // Diminution immédiate du rapport cyclique réel le cas échéant.
  }

  unsigned long currentMillis = millis();
  if (currentMillis - previousMillis >= MainPeriod)
  {
    previousMillis = currentMillis;
    // need to bufferize to avoid glitches
    noInterrupts();
    unsigned long _duration = duration;
    unsigned long _pulsecount = pulsecount;
    duration = 0; // clear counters
    pulsecount = 0;
    interrupts();

    float Freq = 1e6 / float(_duration);    //Duration is in uSecond so it is 1e6 / T

    Freq *= _pulsecount; // calculate F

    int RPMmulti = Freq * 30; //Hertz to RPM 60 60 / (magnet number) = your rpm. i use 2 magnet so 30
    Serial.print(" RPM: ");
    Serial.print(RPMmulti);

    int Speedo = map(RPMmulti, 0, 3000, 0, 99);

    Serial.print(" Speedo: ");
    Serial.print(Speedo);

    Serial.print(" Frequency: ");
    Serial.print(Freq);
    Serial.println("Hz ");

   
    if (insideTHR == 0)
      digitalWrite(Motor, LOW);
    else
      OCR1A = insideTHR;//motor on pin 9

    if (Speedo == 0)
      digitalWrite(SpeedoPin, LOW);
    else
      OCR1B = Speedo;//speedo on pin 10
   
  }
}

void myinthandler() // interrupt handler
{
  unsigned long currentMicros = micros();
  duration += currentMicros - previousMicros;
  previousMicros = currentMicros;
  pulsecount++;
}

void setupTimer1_20Khz()
{
  TCNT1  = 0;//clear Arduino pwm presets
  TCCR1A = 0;
  TCCR1B = 0;
  //set to mode 14 fast pwm to ICR1 top value
  //non inverted output on pins 9 (A) and 10 (B)
  //Clear OC1A/OC1B on Compare Match, set OC1A/OC1B at
  //BOTTOM (non-inverting mode)
  //ICR1 set frequency OCR1A and OCR1B set duty cycle
  //prescaler 8 gives .5 microseconds per timer tick
  // TCCR1A
  // Bit                 7      6      5       4     3      2      1      0
  // Bit Name          COM1A1 COM1A0 COM1B1 COM1B0 -----  ----- WGM11  WGM10
  // Initial Value       0      0      0       0     0      0      0      0
  // changed to        1      0      1       0     0      0      1      0

  TCCR1A = B10100010;

  // TCCR1B  prescaler 8 .5us/tick
  // Bit             7     6      5       4       3      2        1       0
  // Bit Name      ICNC1  ICES1 ----   WGM13    WGM12    CS12    CS11     CS10
  // Initial Value    0     0     0        0       0      0        0       0
  // changed to     0     0     0        1       1      0        1       0

  TCCR1B = B00011010;

  ICR1 = 99;   //Set Top Value, -> frequency 20 kHz with 16 MHz internal clock
 
}