Problem with comunication from PC with python and ARDUINO

Hi, I’ve a problem with the USB comunication from PC with python and
ARDUINOUNO.
I wrote a little python program than can transmit ‘a’ caracter in the USB port
to and ARDUINOUNO.
I just post below my python code than can make that:

import time
import serial
import keyboard
import pynput





try:    
    connect = serial.Serial("/dev/ttyACM0", 115200)
    
    if connect.is_open:
       print ("\n Il collegamento è stato effettuato con successo  \n")

    #ser.close()

except:
    print("""
    Collegamento fallito,
    controllare se il dispositivo è stato connesso correttamente,
    o di avere inserito il nome della porta corretto \n""")


       
    

i=b'a\n'
while 1:   
        if(keyboard.is_pressed('a')):
            connect.write(i)   

This one above transmit le ‘a’ caracter when i press ‘a’ key.
Below I post the code inside ARDUINOUNO than can receive the letter ‘a’.

#include "Arduino.h"
#include "MCP4251.h"
#include "TimerOne.h"
#define MAX_BUFFER 2

//void read_USB();

int elemento_buffer=0;
char buffer[MAX_BUFFER];


#define cs1 2
#define cs2 3
#define cs3 4
#define cs4 5
#define cs5 6
#define cs6 7
#define cs7 8
#define cs8 9
#define cs9 10
#define cs14 14

#define pot0ResistanceRmax 100000 // These resistance values may vary
#define pot0ResistanceRmin 0
#define pot1ResistanceRmax 100000
#define pot1ResistanceRmin 0

extern TimerOne Timer0;
extern TimerOne Timer2;
extern TimerOne Timer3;


      float fr0=879;
      int a1=3300;
      float fr1=1783;
      int a2=9900;
      float fr2=2722;
      int a3=17000;
      float fr3=3565;
      int a4=17800;
      float fr4=6528;
      int a5=19000;
      int mast_vol=20000;
      int vol=0;
      unsigned long tatt = 0;
      unsigned long microsecatt = (tatt / 1000);
      unsigned long tdec = 2000000000;
      unsigned long microsecdec = (tdec / 1000);


MCP4251 f0(cs1, pot0ResistanceRmax, pot0ResistanceRmin, pot1ResistanceRmax, pot1ResistanceRmin);
MCP4251 f1(cs2, pot0ResistanceRmax, pot0ResistanceRmin, pot1ResistanceRmax, pot1ResistanceRmin);
MCP4251 f2(cs3, pot0ResistanceRmax, pot0ResistanceRmin, pot1ResistanceRmax, pot1ResistanceRmin);
MCP4251 f3(cs4, pot0ResistanceRmax, pot0ResistanceRmin, pot1ResistanceRmax, pot1ResistanceRmin);
MCP4251 f4(cs5, pot0ResistanceRmax, pot0ResistanceRmin, pot1ResistanceRmax, pot1ResistanceRmin);
MCP4251 f5(cs6, pot0ResistanceRmax, pot0ResistanceRmin, pot1ResistanceRmax, pot1ResistanceRmin);
MCP4251 f6(cs7, pot0ResistanceRmax, pot0ResistanceRmin, pot1ResistanceRmax, pot1ResistanceRmin);
MCP4251 f7(cs8, pot0ResistanceRmax, pot0ResistanceRmin, pot1ResistanceRmax, pot1ResistanceRmin);
MCP4251 f8(cs9, pot0ResistanceRmax, pot0ResistanceRmin, pot1ResistanceRmax, pot1ResistanceRmin);
MCP4251 f9(cs14, pot0ResistanceRmax, pot0ResistanceRmin, pot1ResistanceRmax, pot1ResistanceRmin);

void setup() {
    Serial.begin(9600);
    f0.begin();
    f0.DigitalPotTerminalBConnect(0);
    f0.DigitalPotTerminalAConnect(0);
    f0.DigitalPotWiperConnect(0);
    f1.begin();
    f1.DigitalPotTerminalBConnect(0);
    f1.DigitalPotTerminalAConnect(0);
    f1.DigitalPotWiperConnect(0);
    f2.begin();
    f2.DigitalPotTerminalBConnect(0);
    f2.DigitalPotTerminalAConnect(0);
    f2.DigitalPotWiperConnect(0);
    f3.begin();
    f3.DigitalPotTerminalBConnect(0);
    f3.DigitalPotTerminalAConnect(0);
    f3.DigitalPotWiperConnect(0);
    f4.begin();
    f4.DigitalPotTerminalBConnect(0);
    f4.DigitalPotTerminalAConnect(0);
    f4.DigitalPotWiperConnect(0);
    f5.begin();
    f5.DigitalPotTerminalBConnect(0);
    f5.DigitalPotTerminalAConnect(0);
    f5.DigitalPotWiperConnect(0);
    f6.begin();
    f6.DigitalPotTerminalBConnect(0);
    f6.DigitalPotTerminalAConnect(0);
    f6.DigitalPotWiperConnect(0);
    f7.begin();
    f7.DigitalPotTerminalBConnect(0);
    f7.DigitalPotTerminalAConnect(0);
    f7.DigitalPotWiperConnect(0);
    f8.begin();
    f8.DigitalPotTerminalBConnect(0);
    f8.DigitalPotTerminalAConnect(0);
    f8.DigitalPotWiperConnect(0);
    f9.begin();
    f9.DigitalPotTerminalBConnect(0);
    f9.DigitalPotTerminalAConnect(0);
    f9.DigitalPotWiperConnect(0);
    //Timer0.initialize(1000000000);
    //Timer0.attachInterrupt(read_USB);
    //Timer1.initialize(microsecdec);  
    //Timer1.attachInterrupt(decay);  
    //interrupts();
    Serial.begin(115200);
    while (!Serial)
      delay(10); // will pause Zero, Leonardo, etc until serial console opens

    Serial.println("OK!");
    //Timer1.initialize(1000000);     //testa se ci sono comandi sulla USB ogni 1msec
    //Timer1.attachInterrupt(read_USB); // read USB to run every 0.15 seconds
}

uint16_t wiper0;
uint16_t wiper1;




float conv_freq4_5(float freq)
{
    float restot;
    restot = 1 / (freq * 0.082);
    restot = restot * 1000000;
    restot = restot - 2200;
    restot = restot / 2;
    return restot;
}

float conv_freq1_2_3(float freq)
{
    float restot;
    restot = 1 / (freq * 6.28 * 0.022);
    restot = restot * 1000000;
    return restot;
}

void freq0(float freq)
{
    float resistenza = conv_freq1_2_3(freq);
    //primo pot. (10K)
    wiper0 = f0.DigitalPotResistanceToPosition(0, resistenza * 2);
    f0.DigitalPotSetWiperPosition(0, wiper0);
    //secondo pot. (10K)
    wiper1 = f0.DigitalPotResistanceToPosition(1, resistenza * 2);
    f0.DigitalPotSetWiperPosition(1, wiper1);
    //terzo pot. dig. (5K)
    wiper0 = f1.DigitalPotResistanceToPosition(0, resistenza);
    f1.DigitalPotSetWiperPosition(0, wiper0);
}

void freq1(float freq)
{
    float resistenza = conv_freq1_2_3(freq);
    //primo pot. (10K)
    wiper1 = f2.DigitalPotResistanceToPosition(1, resistenza * 2);
    f2.DigitalPotSetWiperPosition(1, wiper1);
    //secondo pot. (10K)
    wiper0 = f2.DigitalPotResistanceToPosition(0, resistenza * 2);
    f2.DigitalPotSetWiperPosition(0, wiper0);
    //terzo pot. dig. (5K)
    wiper1 = f1.DigitalPotResistanceToPosition(1, resistenza);
    f1.DigitalPotSetWiperPosition(1, wiper1);
}

void freq2(float freq)
{
    float resistenza = conv_freq1_2_3(freq);
    //primo pot. (10K)
    wiper0 = f3.DigitalPotResistanceToPosition(0, resistenza * 2);
    f3.DigitalPotSetWiperPosition(0, wiper0);
    //secondo pot. (10K)
    wiper1 = f3.DigitalPotResistanceToPosition(1, resistenza * 2);
    f3.DigitalPotSetWiperPosition(1, wiper1);
    //terzo pot. dig. (5K)
    wiper1 = f4.DigitalPotResistanceToPosition(1, resistenza);
    f4.DigitalPotSetWiperPosition(1, wiper1);
}

void freq3(float freq)
{
    float resistenza = conv_freq4_5(freq);
    //pot. 1
    wiper0 = f4.DigitalPotResistanceToPosition(0, resistenza);
    f4.DigitalPotSetWiperPosition(0, wiper0);
    //pot. 2
    wiper1 = f5.DigitalPotResistanceToPosition(1, resistenza);
    f5.DigitalPotSetWiperPosition(1, wiper1);
}

void freq4(float freq)
{
    float resistenza = conv_freq4_5(freq);
    //pot. 1
    wiper0 = f5.DigitalPotResistanceToPosition(0, resistenza);
    f5.DigitalPotSetWiperPosition(0, wiper0);
    //pot. 2
    wiper1 = f6.DigitalPotResistanceToPosition(1, resistenza);
    f6.DigitalPotSetWiperPosition(1, wiper1);
}


void amp1(int amp)
{
  //wiper0 f6
  wiper0 = f6.DigitalPotResistanceToPosition(0, amp);
  f6.DigitalPotSetWiperPosition(0, wiper0); 
}

void amp3(int amp)
{
  //wiper1 f7
  wiper1 = f7.DigitalPotResistanceToPosition(1, amp);
  f7.DigitalPotSetWiperPosition(1, wiper1); 
}

void amp2(float amp)
{
  //wiper0 f7
  wiper0 = f7.DigitalPotResistanceToPosition(0, amp);
  f7.DigitalPotSetWiperPosition(0, wiper0); 
}

void amp4(int amp)
{
  //wiper0 f8
  wiper0 = f8.DigitalPotResistanceToPosition(0, amp);
  f8.DigitalPotSetWiperPosition(0, wiper0); 
}

void amp5(int amp)
{
  //wiper1 f8
  wiper1 = f8.DigitalPotResistanceToPosition(1, amp);
  f8.DigitalPotSetWiperPosition(1, wiper1); 
}

void master_vol(int vol)
{
  //wiper0 f9
  wiper0= f9.DigitalPotResistanceToPosition(0, vol);
  f9.DigitalPotSetWiperPosition(0, wiper0); 
  //wiper1 f9
  wiper1= f9.DigitalPotResistanceToPosition(1, vol);
  f9.DigitalPotSetWiperPosition(1, wiper1); 
}

void cut_off(float ft)
{
  
}

void inviluppo(void)
{
  //attacco a gradino
  if(microsecatt == 0)
      {
        freq0(fr0);
        freq1(fr1);
        freq2(fr2);
        freq3(fr3);
        freq4(fr4);
        amp1(a1);
        amp2(a2);
        amp3(a3);
        amp4(a4);
        amp5(a5);
        master_vol(vol);
      }
      //attacco a rampa variabile
      else
      { 
        freq0(fr0);
        freq1(fr1);
        freq2(fr2);
        freq3(fr3);
        freq4(fr4);
        amp1(a1);
        amp2(a2);
        amp3(a3);
        amp4(a4);
        amp5(a5);
        while(vol!=0)
        { 
          master_vol(vol--);
          //delay(microsecatt);
        }
      }
      //decay 
      while(vol>=0 && vol==mast_vol-5000)
      { 
        master_vol(vol++);
        //delay(1);
      }
      //sustan
      delay(2000);
      //relese
      while(vol<=20000)
      { 
        master_vol(vol++);
        delay(1);
      }
      vol=0;
}


void loop() {
    while((Serial.available())>0) 
  {      
    // se c'è qualche byte da leggere, allora...
    char carattere=Serial.read();      // ...leggi byte
    //if(carattere=='\r') continue;
    if(carattere=='\n')
    {
      buffer[elemento_buffer]=0;       // inserisco un carettere NULL per indicare la fine dell'array
      elemento_buffer=0;               // resetto l'indice dell'array
      break;                           // esco dal ciclo while
    }
    buffer[elemento_buffer]=carattere; // creo l'array di caratteri
    elemento_buffer++;                 // incremento l'indice del buffer
    if(elemento_buffer==MAX_BUFFER)    // se si raggiunge il limite di byte del buffer allora...
    {
      elemento_buffer=MAX_BUFFER-1;    // ...sovrascrivi quello precedente
    } 
  if(buffer[0] == 'a')     
  { 
    inviluppo();
    Serial.println(buffer); 
  }
  buffer[0]='0';    //pulisci buffer
}
}
    

/*void read_USB()
{ 
  //interrompi l'inviluppo per suonare una nuova nota
  if((Serial.available())>0)
  {
    if(buffer[0]=='a')
    {
      Serial.println(buffer); 
      inviluppo();
    }
  }
}*/

This target application is to implement a sinthetizer.
When i press ‘a’ ARDUINOUNO play a frequency with inviluppo() function, but the frequency
was played every 1 second without a trasmission of letter ‘a’, why? I don’t know.
I need to implement an ARDUINO application than play a note when I press ‘a’, but that does’t append, and I don’t know why.
Can you help me please to understand why it doesn’t append?
Thank you so much.

Hi,

there are two recommendations for your C code:

You have two functions that perform unnecessary math calculations which you can take care of beforehand. Here, I have removed a few lines of code each saving a number of clock cycles which may be valuable in time critical code.

float conv_freq4_5(float freq)
{
    float restot  = 6097561 / freq - 1100; 
    return restot;
}


float conv_freq1_2_3(float freq)
{
   float restot = 7237985 / freq;
   return restot;
}

Also, don’t use the delay function

 delay(2000);

This freezes up your controller until it finishes the count. Instead use a timer. For example, if the value is in microseconds, set up your timer to increment every 1 microsecond. Have a variable increment inside the timer interrupt. Couple this with a while conditional statement like this:

while(countValue < 2001); # Wait here until count reaches threshold

This unfreezes your controller from only focusing on the delay function especially if the delay function is set up with a higher interrupt priority (IPx value) than other peripherals.

I also have questions for what appears to be calibration functions for different values of potentiometer resistance values. For example, in the following function, it appears that the wiper1 variable is immediately overwritten before it is even used.

void freq2(float freq)
{
    float resistenza = conv_freq1_2_3(freq);
    //primo pot. (10K)
    wiper0 = f3.DigitalPotResistanceToPosition(0, resistenza * 2);
    f3.DigitalPotSetWiperPosition(0, wiper0);
    //secondo pot. (10K)
    wiper1 = f3.DigitalPotResistanceToPosition(1, resistenza * 2);  // Calculate value here
    f3.DigitalPotSetWiperPosition(1, wiper1);
    //terzo pot. dig. (5K)
    wiper1 = f4.DigitalPotResistanceToPosition(1, resistenza);  // Overwritten here
    f4.DigitalPotSetWiperPosition(1, wiper1);
}

Check functions with similar code.

In the Python code, don’t use a “bare” except because it catches any exception. Catch only what you’re going to handle.

In the Arduino code, in `inviluppo’, you have:

    while (vol >= 0 && vol == mast_vol - 5000) {

Is that correct?

In loop, you have:

Serial.println(buffer);

but you never put a null terminator after the character you put in the buffer.

Suppose you tap the a key on the keyboard very quickly. How many times do you think the loop can run, until the key actually rises back up? Therefore, how many times would the while((Serial.available())>0) loop run in the C code?

I don’t know how many times it read the caracter inside C code in ARDUINO.
I need to break the code in inviluppo(), with a timer interrupt at any time when I press the key ‘a’ again.
When i press the ‘a’ key again I want then the intviluppo() is iterrupter from an interrupt function
for play a note again. When I put the interrupt code I hear in the headphone a bad sound and not
the effect desired.
Can you halp me to get the just effect desired inside the C code? How can I make that effect?

On an Ardunio, using delay means that it won’t be dong anything else for that time, as @onePythonUser said.

What you can do instead is use variables to indicate the current state and when it entered that state.

Here’s a simple example that blinks the LED on pin 13 without using delay:

#define ONE_SECOND 1000

#define LED_PIN 13

bool ledOn;
uint32_t stateTime;

void setup() {
    pinMode(LED_PIN, OUTPUT);
    ledOn = false;
    stateTime = millis();
}

void loop() {
    uint32_t now;
    
    now = millis();
    
    if (now - stateTime >= ONE_SECOND) {
        ledOn = !ledOn;
        stateTime = now;
        digitalWrite(LED_PIN, ledOn);
    }
}

In this example there’s only 1 state to deal with, and it’s only on/off.

In other code there might be many things that each have many states, and you’d use switch statements to handle each of them.