Python Arduino serial communication

Hello,
I am trying to use Arduino to generate PWM signals and modify the frequency of PWM signals wile they are running using a user interface created with Python. I tried doing so with Pyserial.

When modifying frequency through Arduino's serial monitor it works properly. However, when I try to change the frequency with through Python there is no change. What could be the problem?

In Python the frequency change should happen at def start after presing the button

Arduino code:

float freq = 109000;
float duty_cycle = 0.3;
int set;
void setup() {
  pinMode(9, OUTPUT); //output A
  pinMode(10, OUTPUT); //output B
 
  TCCR1A = 0; //clear timer registers
  TCCR1B = 0;
  TCNT1 = 0;

  TCCR1B |= _BV(CS10); //no prescaler
  //ICR1 = 73;//freq = 7987412/ICR1;
  //OCR1A = 52;
  //OCR1A = 0.7297*ICR1;
  //OCR1B = ICR1 - OCR1A;

  //OCR1A = 20; //Pin 9 match
  //output A set rising/clear falling
  TCCR1A |= _BV(COM1A1) | _BV(COM1A0); //output A set rising/clear falling

  //OCR1B = 54; //Pin 10 match
  //output B clear rising/set falling
  TCCR1A |= _BV(COM1B1); //output B clear rising/set falling

  TCCR1B |= _BV(WGM13); //PWM mode with ICR1 Mode 10
  TCCR1A |= _BV(WGM11); //WGM13:WGM10 set 1010
  Serial.begin(9600);
  //ICR1 = 73;//freq = 7987412/ICR1;
  //OCR1A = 50;
  //OCR1B = ICR1 - OCR1A;

}

void loop() {
  if(duty_cycle>0.4){
    duty_cycle = 0.4;
  }
  set = 7987412/freq;
  ICR1 = set;//freq = 7987412/ICR1;
  OCR1B = duty_cycle*ICR1;
  OCR1A = ICR1 - OCR1B;
  if(ICR1>0){
    Serial.println(ICR1);
    delay(500);

  }
  if(Serial.available()>0){

    freq = Serial.parseFloat();

    
  }
  }

Python code:

import sys
import PyQt5
from PyQt5.QtWidgets import *
from PyQt5.QtCore import *
from PyQt5.QtGui import *
import sys
import serial
import time
import serial.tools.list_ports
import struct

class MainWindow(QMainWindow):
    def __init__(self):
        super(MainWindow, self).__init__()
        self.setWindowTitle("Arduino GUI")
        self.setFixedSize(QSize(800,640))

        global pagelayout
        pagelayout = QVBoxLayout()
        button_layout = QHBoxLayout()
        label_layout = QHBoxLayout()
        spinbox_layout = QHBoxLayout()
        port_layout = QHBoxLayout()
        freq_layout = QHBoxLayout()
        self.stacklayout = QStackedLayout()


        pagelayout.addLayout(button_layout)
        pagelayout.addLayout(label_layout)
        pagelayout.addLayout(spinbox_layout)
        pagelayout.addLayout(port_layout)
        pagelayout.addLayout(freq_layout)
        pagelayout.addLayout(self.stacklayout)

        #Port button
        btn = QPushButton("Port")
        btn.pressed.connect(self.find_port)
        button_layout.addWidget(btn)

        #Start button
        btn = QPushButton("Start")
        btn.pressed.connect(self.start)
        button_layout.addWidget(btn)

        #Stop button
        btn = QPushButton("Stop")
        btn.pressed.connect(self.stop)
        button_layout.addWidget(btn)

        #Freq label
        label = QLabel("Frequency")
        label_layout.addWidget((label))

        #DC label
        label = QLabel("Duty cycle")
        label_layout.addWidget((label))

        #Freq spinbox
        global spnb_f
        spnb_f = QDoubleSpinBox()
        spinbox_layout.addWidget(spnb_f)
        spnb_f.setDecimals(0)
        spnb_f.setMinimum(10000)
        spnb_f.setMaximum(500000)
        spnb_f.setSingleStep(1)


        #DC spinbox
        spnb_dc = QDoubleSpinBox()
        spinbox_layout.addWidget(spnb_dc)
        spnb_dc.setMinimum(0.1)
        spnb_dc.setMaximum(0.4)
        spnb_dc.setSingleStep(0.1)

        #Port
        global port_label
        port_label = QLabel("Port: ")
        port_layout.addWidget(port_label)


        #FreqData
        global flabel
        flabel = QLabel("Frequency: ")
        freq_layout.addWidget(flabel)


        widget = QWidget()
        widget.setLayout(pagelayout)
        self.setCentralWidget(widget)

    def find_port(self):
        global thePort
        global arduino
        commports = serial.tools.list_ports.comports()
        numPorts = len(commports)
        if numPorts == 0:
            port_label.setText("Port: not available")
            return
        if (numPorts > 1):
            portNum = 0
            for port in commports:
                print("port number", portNum)
                print(port)
                portNum = portNum+1
            usePort = int(input("enter port number to use 0-"+str(numPorts-1)+':'))
            port.setText("yep")
        else:
            usePort = 0

        time.sleep(1)
        thePort = commports[usePort][0]
        port_label.setText(str("Port: "+str(thePort)))


    def start(self):
        global frequency
        #try:
        arduino = serial.Serial(thePort, baudrate=9600, timeout=2)
        time.sleep(2)
        frequency = spnb_f.value()
        flabel.setText(str("Frequency: "+str(frequency)))
        print(type(frequency))
        arduino.write(struct.pack('!f',frequency))
        #except:
        flabel.setText("Frequency: error. Port not connected or unavailable.")

    def stop(self):
        self.stacklayout.setCurrentIndex(1)





app = QApplication(sys.argv)
window = MainWindow()
window.show()
app.exec_()

What do you see if you print the value of freq after reading it ?

I think your code expects the float formated as ASCII.

Could you try this?

import time

arduino = serial.Serial(thePort, baudrate=9600, timeout=2)
arduino.write(b"50.0\n")

time.sleep(10000)
1 Like

Printing freq outputs the freq value as a float. For example:
109000.00

I tried this line of code and it seems that Arduino reacts to it. However, instead of setting a different frequency, it sets one channel to 0 V and other to 5V and crashes after a few miliseconds

I figured out why this happens. I had to delete the \n for the Arduino to run continuously and it works fine. It appears that I also had to encode the variable before sending it so now everything works. Thanks for the help!

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.