I would like to turn on and off the output of two pins on my arduino independently from each other. However, so far all my attempts have failed.

My current idea is to save the status (which I chose to be 0 as 'low' and 'high' as 1) of each of the pins in an integer array and then change the status of the pin depending of the entry in the variable. However, the entries in the variable are always set back to 0 and I do not know why this is happening.

This is my arduino code

const byte numChars = 32;
byte receivedChars[numChars];
boolean newData = false;
const int num_of_pins=2;
int output_pins[num_of_pins]={22,26};
int status_pins[num_of_pins]={0,0};


void setup() {
    int ii=0;
    Serial.begin(9600);
    for(ii=0; ii<num_of_pins; ii++){      
        pinMode(output_pins[ii],OUTPUT);      
    }


}

void loop() {
    recvWithStartEndMarkers();
    chooseFunction();   
}

void chooseFunction(){
  if (receivedChars[0]==0){
    shutter();
    }
}

void shutter(){
        // get number of pin
        int pin_number_rcvd;
        int ii;
        int pin_status_rcvd;
        pin_number_rcvd=receivedChars[1];
        pin_status_rcvd=receivedChars[2];
        //check all status of pins and turn on and off
        for (ii=0; ii<num_of_pins; ii++){
          if (pin_number_rcvd==output_pins[ii]){
            status_pins[ii]=pin_status_rcvd;
          }
          if (status_pins[ii]==0){
            digitalWrite(output_pins[ii],LOW);
          }
          if (status_pins[ii]==1){
            digitalWrite(output_pins[ii],HIGH);
          }
        }
}

void recvWithStartEndMarkers() {
    static boolean recvInProgress = false;
    static byte ndx = 0;
    byte startMarker = 8;
    byte endMarker = 9;
    byte rc;


    while (Serial.available() > 0 && newData == false) {
        rc = Serial.read();

        if (recvInProgress == true) {
            if (rc != endMarker) {
                receivedChars[ndx] = rc;
                ndx++;
                if (ndx >= numChars) {
                    ndx = numChars - 1;
                }
            }
            else {
                receivedChars[ndx] = '\0'; // terminate the string
                recvInProgress = false;
                ndx = 0;
                newData = true;
            }
        }

        else if (rc == startMarker) {
            recvInProgress = true;
        }
    }
}

I use pyserial to send the input data to the arduino. my python code:

import serial
import time, struct, sys
ser=serial.Serial('COM17', 9600, timeout=10)
time.sleep(2)
ser.reset_input_buffer()
ser.reset_output_buffer()
pin_number= int(sys.argv[1])
high_or_low=int(sys.argv[2])

ser.write(struct.pack('>5B',8,1,pin_number,high_or_low,9))

I am using an ArduinoDue together with the arduino IDE.

  • Maybe it isn't it, but you are expecting: receivedChars[0]==0 but ser.write(struct.pack('>5B',8,1,pin_number,high_or_low,9)) is sent (eg it's 1, not 0) – KIIV Sep 14 at 10:48
  • thanks for your answer. Unfortunately, it does not change anything – anonymous Sep 14 at 11:01
  • you left our some information .... the following description does not explain why python script is involved .... I would like to turn on and off the output of two pins on my arduino independently from each other. – jsotola Sep 14 at 15:27
  • Thats true. Sorry for that. I want to switch the output on the board on and off using python, e.g. I want to send data to the arduino with pyserial telling the arduino to switch on or off the output on a certain pin. – anonymous Sep 14 at 15:32
  • I think I figured iut the problem, but I still do not know how to solve it. The problem is that whenever I want to switch the output on or off, I restart the python script which completely resets the arduino and therefore the output on all the other channels is switched off – anonymous Sep 14 at 15:33

Your problem is in one tricky option for arduino's com connection. When you reopen COM port where arduino is connected your arduino resets automatically.

Here's workaround from arduino.cc:

DisablingAutoResetOnSerialConnection

The simple way that doesn't require any permanent modifying of your hardware or software configuration changes:

Stick a 120 ohm resistor in the headers between 5v and reset (you can find these on the isp connector too). 120 is hard to find so just combine resistors. Don't go below 110 ohms or above 124 ohms, and don't do this with an isp programmer attached. You can just pull out the resistor when you want auto-reset back.

http://playground.arduino.cc/Main/DisablingAutoResetOnSerialConnection

Or you can just modify you script to be able to start over without reopening it. For example use a loop there and some exit command to end that loop:

try:
    while True:
        do_something()
except KeyboardInterrupt:
    pass

https://stackoverflow.com/questions/13180941/how-to-kill-a-while-loop-with-a-keystroke Replace do_something() with this part of your code:

ser.reset_input_buffer()
ser.reset_output_buffer()
pin_number= int(sys.argv[1])
high_or_low=int(sys.argv[2])

ser.write(struct.pack('>5B',8,1,pin_number,high_or_low,9))

I hope I was clear enough.

Your Answer

 

By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.

Not the answer you're looking for? Browse other questions tagged or ask your own question.