Problems with multiple PIRs launching videos

Hello there, I was wondering if anyone could offer some advice on my code to launch multiple videos using arduino and python. First the arduino code.

const byte pir1 = 7;           // choose the input pin (for PIR sensor)
const byte pir2 = 8;           // choose the input pin (for PIR sensor)

byte pirState;  // we start, assuming no motion detected
byte pirState2;

const long deltime = 150;   

void setup()
{
  pinMode(pir1, INPUT);     // declare sensor as input
  pinMode(pir2, INPUT);     // declare sensor as input
  eMotion1();
  eMotion2();
  pirMode1();
  pirMode2();
  Serial.begin(9600);
}

void loop() {
  pirState = digitalRead(pir1);
  
  while (pirState == HIGH){
    eMotion1();
    break;
  }

  pirState2 = digitalRead(pir2);

  while (pirState2 == HIGH){
    eMotion2();
    break;
  }
  
}

void eMotion1()
{
  if (pirState > 0) // check if input(s) is HIGH
  {
    pirMode1();
    delay(300000);
  }
  else
  {
    Serial.print("Motion not detected!");
    delay(deltime);
  }
}

void eMotion2()
{
   if (pirState2 > 0) // check if input(s) is HIGH
  {
    pirMode2();
    delay(300000);
  }
  else
  {
    Serial.print("Motion not detected!");
    delay(deltime);
  }
}

void pirMode1()
{
  Serial.println("PIR A");
}

void pirMode2()
{
  Serial.println("PIR B");
}

I'm experimenting with 2 videos until I can get rid of all the bugs. Things run but a bit shakily, the videos will be 5mins or so each so I've incorporated this into the arduino code using the serial readline to launch the videos in the following python code.

import subprocess
import os
import serial
import time
import vlc

ser = serial.Serial('COM15', 9600)

def launchvid():
    print os.path.exists("C:/stuff/mus.mp4")
    p = subprocess.Popen(["C:/Program Files/VideoLAN/VLC/vlc.exe","stuff/mus.mp4",'--play-and-exit', '--fullscreen'], shell=False)
    print ("")

def launchvid2():
    print os.path.exists("C:/stuff/Born into this.mp4")
    p = subprocess.Popen(["C:/Program Files/VideoLAN/VLC/vlc.exe","stuff/Born into this.mp4",'--play-and-exit', '--fullscreen'], shell=False)   
    print("")

while True:
    message = ser.readline()
    print(message)
    try:
        if message[4] == "A":
             launchvid()
        time.sleep(0.5)
        print("A done")
        except IndexError: launchvid()

    try:
        if message[4] == "B" :
            launchvid2()
        time.sleep(0.5)
        print("B done")
        except IndexError: launchvid2()

I imagine the except indexerror may have something to do with this but I'm at my wits end trying to figure it out. I've also used vlc bindings within. Thanks for your time in advance.

This may be your problem:

Serial.print("Motion not detected!");

Change to println.

In your python you are using readline, and when there is no PIR this will go out WITHOUT a newline. Your python is reading until it finds a newline (or times out if configured) so the string it eventually returns could easily be something like:

"Motion not detected!Motion not detected!Motion not detected!PIR A\n"

Then the Python is only looking at message[4] and will clearly not be "A" or "B".

Thanks for your reply dDeters, yes I see now how the indexerror keeps happening. I have tried to modify the python code stop the index error and incorporate the video that will loop while the others wait to be triggered but the indexerror pops up again.

Arduino code

const byte pir1 = 7;           // choose the input pin (for PIR sensor)
const byte pir2 = 8;           // choose the input pin (for PIR sensor)

byte pirState;  // we start, assuming no motion detected
byte pirState2;

const long deltime = 150;   

void setup()
{
  pinMode(pir1, INPUT);     // declare sensor as input
  pinMode(pir2, INPUT);     // declare sensor as input
  eMotion1();
  eMotion2();
  pirMode1();
  pirMode2();
  Serial.begin(9600);
}

void loop() {
  pirState = digitalRead(pir1);
  
  while (pirState == HIGH){
    eMotion1();
    break;
  }

  pirState2 = digitalRead(pir2);

  while (pirState2 == HIGH){
    eMotion2();
    break;
  }
  
}

void eMotion1()
{
  if (pirState > 0) // check if input(s) is HIGH
  {
    pirMode1();
    delay(300000);
  }
  else
  {
    Serial.println("Motion not detected!\n");
    delay(deltime);
  }
}

void eMotion2()
{
   if (pirState2 > 0) // check if input(s) is HIGH
  {
    pirMode2();
    delay(300000);
  }
  else
  {
    Serial.println("Motion not detected!\n");
    delay(deltime);
  }
}

void pirMode1()
{
  Serial.println("PIR A\n");
}

void pirMode2()
{
  Serial.println("PIR B\n");
}

New python code (that doesn't work, still gives IndexError: string index out of range)

import subprocess
import os
import serial
import time
import vlc
import sys

ser = serial.Serial('COM15', 9600)

def launchvid():
    print os.path.exists("C:/stuff/mus.mp4")
    print("")
    p = subprocess.Popen(["C:/Program Files/VideoLAN/VLC/vlc.exe","stuff/mus.mp4",'--play-and-exit', '--fullscreen'], shell=False)

def launchvid2():
    print os.path.exists("C:/stuff/Born into this.mp4")
    print("")
    p = subprocess.Popen(["C:/Program Files/VideoLAN/VLC/vlc.exe","stuff/Born into this.mp4",'--play-and-exit', '--fullscreen'], shell=False)   
    
    
def launchvid3():
    print os.path.exists("E:/At Home With Gen.mp4")
    print("")
    p = subprocess.Popen(["C:/Program Files/VideoLAN/VLC/vlc.exe","E:/At Home With Gen.mp4",'--input-repeat=-1', '--no-video-title-show', '--fullscreen', '--mouse-hide-timeout=0'], shell=False)
    
while True:
    message = ser.readline()
    print(message)
    try:
        if message[0] == "M":
             launchvid3()
        sys.stdout.write('')
        
    except:
        if message[4] == "A":
             launchvid()
        time.sleep(0.5)
        sys.stdout.write('')
        
    else:
        if message[4] == "B" :
            launchvid2()
        time.sleep(0.5)
        sys.stdout.write('')

    finally:
        launchvid3()

Thanks again for your valuable reply, does anyone know how to keep a video looping if its on another partition(such as a usb drive). I'm not sure this will work unless the files are on the same partition as vlc?

while (pirState == HIGH){
    eMotion1();
    break;
 }

Seems torturous and unnecessarily complex. Why not just use an ‘if’ statement?

if (pirState == HIGH) {
    eMotion1();
}

Yes that makes sense, thank you for your reply.

Hallo everybody, so I've simplified the python code as follows.

import subprocess
import os
import serial
import time
import sys

ser = serial.Serial('COM15', 9600)

def launchvid():
    p = subprocess.Popen(["C:/Program Files/VideoLAN/VLC/vlc.exe","stuff/mus.mp4",'--play-and-exit', '--fullscreen'], shell=False)

def launchvid2():
    p = subprocess.Popen(["C:/Program Files/VideoLAN/VLC/vlc.exe","stuff/Born into this.mp4",'--play-and-exit', '--fullscreen'], shell=False)
    
def launchvid3():
    p = subprocess.Popen(["C:/Program Files/VideoLAN/VLC/vlc.exe","Arduino SPI.mp4",'--input-repeat=999999', '--fullscreen',], shell=False)
    
while True:
    message = ser.readline()
    print(message)

    message[-0] == {"A":launchvid(), "B":launchvid2(),"!":launchvid3()}

But the outputs still a bit all over the place, I set vlc in the preferences to use only one instance. I will also be using the delay block timed to the exact length of the videos I will be using to make sure the serial println isn't bombarded with messages from the PIR triggering.

So say I want launchvid3() to continually run unless A triggers launchvid() or B triggers launchvid2() and for when A or B finish to go back to launchvid3() to continually run unless either PIR is triggered. Could anyone advise how I could do this or point me in the direction of figuring this out. Thanks for your time in advance and may the road rise with you.