純粋なPythonの記事ではありませんが、エラー解決ができた事例がありましたので記事にしました。
私はArduino(アルドゥイーノ)が好きで、ロボット制御や簡単なIoTシステムを構築しています。
「PythonからArduinoを制御できる」と聞き、やってみたところLチカでつまづきました笑。
その際に色々調べた結果、一つの解決策がヒットしましたので公開します。
あくまで一つの解決策であり、誰しも当てはまる事例ではないかもしれませんが、お役に立てれば幸いです。
実行環境
まず、私の環境を簡単に紹介しておきます。
- Windows10/11
- Arduino IDE 2.1.0
- Arduino本体 UNO R3とUNO R4 MINIMAを使用
- Python 3.9
- PySerial 3.5
上記はそれほど影響がないと思われます。
Arduino本体はUNO R3とUNO R4 MINIMAを試しました。
これ以外のArduinoをお使いの場合は解決できない場合があります。
ちなみに、PythonからArduinoを制御するための方法はいくつかあるようですが、私はPySerialというライブラリを利用する方法を使っています。
以降の解説はPySerialに関するスクリプトの例を提示します。
実行したコードの公開
もし、私と同じようにPythonからArduinoのLチカをやってみたいという場合、以下のコードとスクリプトを試してもらうとできるはずです。
Arduinoのコード
本体の13番ピンに直結しているLEDを点滅させる基本コードとして、「Lチカ」を実行できます。
ただし、純粋にArduinoだけで実行するBlink(Lチカ)と異なる点は「Pythonから送信された値によって制御する」という処理をswitch/caseで実現していることです。
void setup() {
  Serial.begin(9600);
   
  pinMode(13, OUTPUT);
  digitalWrite(13, LOW);
}
  
void loop() {
  byte var;
  var = Serial.read();
 
  switch(var){
    case '0':
      digitalWrite(13, HIGH);
      break;
    case '1':
      digitalWrite(13, LOW);
      break;
    default:
      break;
  }
}
最初にこれをArduino本体に書き込んでおく必要があります。
この時点でエラーが出る場合、本記事の解決策では対応できません。
Pythonのスクリプト
今回の目的はLチカなので、LEDの点灯と消灯を1秒ずつ繰り返す処理のみです。
Arduinoでは1秒=1000ミリ秒を「delay(1000)」としますが、Pythonではtime.sleepによって1秒を指示しています。
import serial
import time
# 第一引数について:Macなら「'/dev/ttyUSB0'」、Windowsなら「'COM8'」と記述
ser = serial.Serial('COM8', 9600)
while True:
    # LEDの点灯と消灯を1秒ずつ繰り返す(=点滅する)
    ser.write(b"1")
    time.sleep(1)
    ser.write(b"0")
    time.sleep(1)上記はWindowsにおいてArduinoを接続したUSBポートが「COM8」の場合の書き方です。
これはお使いの環境によって異なるため、確認してください。
参考までに、以下はUNO R4を接続したUSBポートが「COM6」となっているため、この場合は「ser = serial.Serial(‘COM6’, 9600)」とすればOKです。

また、Macの場合はWindowsと異なり、「ser = serial.Serial(‘/div/ttyUSB0’, 9600)」のようになります。
※手元にmacがなかったので、画面キャプチャは紹介できませんでした。
なお、上記はPySerialをインストール済みであれば実行できます。
pip install pyserialまたは
pip3 install pyserialが必要です。
エラーの状況
PC→Arduinoへの書き込み時はエラーもなくコンパイルできたけど、Pythonのスクリプトを実行したときにエラーが出る場合の解決策を紹介します。
対象外のエラー
ただ、この時点でエラーが出るという場合、この記事の解決策は役に立ちません。
Arduinoのプログラムを見直すか、USBケーブルの接続状況を見直しましょう。
また、Arduino本体が互換品だと問題が起きる場合も多くあります。
上のような青い基盤のものは互換品と言われ、難ありなものが多く存在します。
安くて良いのですが、おススメしません。
対象となるエラー
Pythonのスクリプトを実行したとき、以下のエラーが出る場合は以降の解説を参考にしてください。
C:\pythonarduino\Scripts\python.exe C:\papa3\pythonarduino\sketch_oct23a\main.py 
Traceback (most recent call last):
  File "C:\papa3\pythonarduino\sketch_oct23a\main.py", line 5, in <module>
    ser = serial.Serial('COM8', 9600)
  File "C:\pythonarduino\lib\site-packages\serial\serialwin32.py", line 33, in __init__
    super(Serial, self).__init__(*args, **kwargs)
  File "C:\pythonarduino\lib\site-packages\serial\serialutil.py", line 244, in __init__
    self.open()
  File "C:\pythonarduino\lib\site-packages\serial\serialwin32.py", line 64, in open
    raise SerialException("could not open port {!r}: {!r}".format(self.portstr, ctypes.WinError()))
SerialException: could not open port 'COM8': PermissionError(13, 'アクセスが拒否されました。', None, 5)ただし、上記のように「アクセスが拒否されました」ではなく、
serial.serialutil.SerialException: could not open port 'COM8': FileNotFoundError(2, '指定されたファイルが見つかりません。', None, 2)のように「指定されたファイルがみつかりません」と表示される場合、Pythonスクリプト内のポート番号が間違っている可能性があります。
正しいポート番号に直すだけで、エラーが解決するかもしれません。
エラーの解決方法
ここからは、エラーが「PermissionError ‘アクセスが拒否されました」の場合の解決策を提示します。
よく目にする解決策
私が困ったとき、ググって出てきた情報をまとめると、
- ・Pythonスクリプトを管理者で実行する
- ・コマンドプロンプトを管理者で起動してPythonスクリプトを実行する
- ・Pythonスクリプト内に管理者権限を追記する
- ・バッチファイルを作ってそこにPythonスクリプトのリンクを貼って管理者権限で…
という解説が多かったです。
しかし、私の場合はそれでは解決ができませんでした。
実際に解決できた方法
非常に簡単だったのですが、「Pythonスクリプト実行時にArduino IDEを閉じる」ということでエラーが消えLチカが実行できました。
一度Arduinoにスケッチを書き込んでしまえば、Arduino IDEを起動している必要がありませんから問題ありませんね。
これで解決できた理由は「シリアルモニターを開いているなどUSBを通して「シリアル通信」が行われているとアクセスできないから」だと考えられます。
それが「アクセスが拒否された」という理由ではないでしょうか。
(これは個人的な見解のため、誤りである可能性が高いです。)
理由はどうであれ、無事に実行できるようになれば幸いです。
まとめ
今回は「PySerialでPermissionError’アクセスが拒否されました’」というエラーを解決する方法について解説しました。
もし、この記事の内容でも解決できないという場合、コメントやフォームにてご質問ください。
今後もPythonを中心としたプログラミングの情報をお届けします。
以下のメルマガにご登録頂くと、不定期に配信をお届けします。
ぜひ購読してください!
それでは、ステキなPythonライフを!
 
	
 
	
 
	
 
	



