0

I am using raspberry pi model 3. I was exploring RPi.GPIO library and I realized that the code shown below works in python 3.4 but not in python 2.7. The worst part is I am not getting any error messages when I run in python 2.7 which makes it difficult to trace the error. I tried to search for support online, but couldn't get any decent resource. Could anyone provide me a solution or resource to make this code work in python 2.7?

# LED Blinks (Python3)
# The code will turn ON LED for a second and turn OFF LED for a second in a infinite loop

import RPi.GPIO as GPIO
from time import sleep

GPIO.setmode(GPIO.BOARD)

GPIO.setup(12, GPIO.OUT)

try:
    while True:
        GPIO.output(12, 1)
        sleep(1)
        GPIO.output(12,0)
        sleep(1)

except KeyboardInterrupt:
    GPIO.cleanup()
  • Could you edit your question and include full details of any error messages? – joan Sep 30 '16 at 5:11
  • The code as presented works in both Python 2 (2.7) and Python 3 (3.4) on my jessie Pi3 system. – joan Sep 30 '16 at 8:15
  • Can you add a GPIO.setwarnings(True) before GPIO.setmode(GPIO.Board) and see if any warnings are shown ? – Shreyas Murali Oct 1 '16 at 5:31
  • GPIO.output(12,True) GPIO.output(12,False) Will work... – Arun Jun 20 '17 at 10:03
2

Try replacing the 1 with GPIO.HIGH and 0 with GPIO.LOW like so

# LED Blinks (Python3)
# The code will turn ON LED for a second and turn OFF LED for a second in a infinite loop

import RPi.GPIO as GPIO
from time import sleep

GPIO.setmode(GPIO.BOARD)

GPIO.setup(12, GPIO.OUT)

try:
    while True:
        GPIO.output(12, GPIO.HIGH)
        sleep(1)
        GPIO.output(12, GPIO.LOW)
        sleep(1)

except KeyboardInterrupt:
    GPIO.cleanup()

Notes

Within the source archive, is a file source/constants.c which contains the following function definition

void define_constants(PyObject *module)
{
   high = Py_BuildValue("i", HIGH);
   PyModule_AddObject(module, "HIGH", high);

   low = Py_BuildValue("i", LOW);
   PyModule_AddObject(module, "LOW", low);

   output = Py_BuildValue("i", OUTPUT);
   PyModule_AddObject(module, "OUT", output);

   input = Py_BuildValue("i", INPUT);
   PyModule_AddObject(module, "IN", input);

   pwm = Py_BuildValue("i", PWM);
   PyModule_AddObject(module, "HARD_PWM", pwm);

   serial = Py_BuildValue("i", SERIAL);
   PyModule_AddObject(module, "SERIAL", serial);

   i2c = Py_BuildValue("i", I2C);
   PyModule_AddObject(module, "I2C", i2c);

   spi = Py_BuildValue("i", SPI);
   PyModule_AddObject(module, "SPI", spi);

   unknown = Py_BuildValue("i", MODE_UNKNOWN);
   PyModule_AddObject(module, "UNKNOWN", unknown);

   board = Py_BuildValue("i", BOARD);
   PyModule_AddObject(module, "BOARD", board);

   bcm = Py_BuildValue("i", BCM);
   PyModule_AddObject(module, "BCM", bcm);

   pud_off = Py_BuildValue("i", PUD_OFF + PY_PUD_CONST_OFFSET);
   PyModule_AddObject(module, "PUD_OFF", pud_off);

   pud_up = Py_BuildValue("i", PUD_UP + PY_PUD_CONST_OFFSET);
   PyModule_AddObject(module, "PUD_UP", pud_up);

   pud_down = Py_BuildValue("i", PUD_DOWN + PY_PUD_CONST_OFFSET);
   PyModule_AddObject(module, "PUD_DOWN", pud_down);

   rising_edge = Py_BuildValue("i", RISING_EDGE + PY_EVENT_CONST_OFFSET);
   PyModule_AddObject(module, "RISING", rising_edge);

   falling_edge = Py_BuildValue("i", FALLING_EDGE + PY_EVENT_CONST_OFFSET);
   PyModule_AddObject(module, "FALLING", falling_edge);

   both_edge = Py_BuildValue("i", BOTH_EDGE + PY_EVENT_CONST_OFFSET);
   PyModule_AddObject(module, "BOTH", both_edge);
}

the constant HIGH is defined in source/c_gpio.h like so

#define HIGH 1
#define LOW  0

My best guess is internally within python 2.7 there is a object reference comparison to GPIO.HIGH to set the pin HIGH rather a value comparison to the contant HIGH (equal to 1) and somehow this has changed (to value comparison rather than reference comparison) within python 3. So when passing 1 works for python 3 and not with 2.7


Update 1

I looked at the samples over here and nowhere is a 1 constant used in place of GPIO.HIGH or 0 for GPIO.LOW which is probably why it works.


Update 2 : Further Digging

Looking over the source/py_gpio.c lines 331 through 480

static PyObject *py_output_gpio(PyObject *self, PyObject *args)
{
   unsigned int gpio;
   int channel = -1;
   int value = -1;
   int i;
   PyObject *chanlist = NULL;
   PyObject *valuelist = NULL;
   PyObject *chantuple = NULL;
   PyObject *valuetuple = NULL;
   PyObject *tempobj = NULL;
   int chancount = -1;
   int valuecount = -1;

   int output(void) {
      if (get_gpio_number(channel, &gpio))
          return 0;

      if (gpio_direction[gpio] != OUTPUT)
      {
         PyErr_SetString(PyExc_RuntimeError, "The GPIO channel has not been set up as an OUTPUT");
         return 0;
      }

      if (check_gpio_priv())
         return 0;

      output_gpio(gpio, value);
      return 1;
   }

   if (!PyArg_ParseTuple(args, "OO", &chanlist, &valuelist))
       return NULL;

#if PY_MAJOR_VERSION >= 3
   if (PyLong_Check(chanlist)) {
      channel = (int)PyLong_AsLong(chanlist);
#else
   if (PyInt_Check(chanlist)) {
      channel = (int)PyInt_AsLong(chanlist);
#endif
      if (PyErr_Occurred())
         return NULL;
      chanlist = NULL;
   } else if (PyList_Check(chanlist)) {
      // do nothing
   } else if (PyTuple_Check(chanlist)) {
      chantuple = chanlist;
      chanlist = NULL;
   } else {
       PyErr_SetString(PyExc_ValueError, "Channel must be an integer or list/tuple of integers");
       return NULL;
   }

#if PY_MAJOR_VERSION >= 3
   if (PyLong_Check(valuelist)) {
       value = (int)PyLong_AsLong(valuelist);
#else
   if (PyInt_Check(valuelist)) {
       value = (int)PyInt_AsLong(valuelist);
#endif
      if (PyErr_Occurred())
         return NULL;
       valuelist = NULL;
   } else if (PyList_Check(valuelist)) {
      // do nothing
   } else if (PyTuple_Check(valuelist)) {
      valuetuple = valuelist;
      valuelist = NULL;
   } else {
       PyErr_SetString(PyExc_ValueError, "Value must be an integer/boolean or a list/tuple of integers/booleans");
       return NULL;
   }

   if (chanlist)
       chancount = PyList_Size(chanlist);
   if (chantuple)
       chancount = PyTuple_Size(chantuple);
   if (valuelist)
       valuecount = PyList_Size(valuelist);
   if (valuetuple)
       valuecount = PyTuple_Size(valuetuple);
   if ((chancount != -1 && chancount != valuecount && valuecount != -1) || (chancount == -1 && valuecount != -1)) {
       PyErr_SetString(PyExc_RuntimeError, "Number of channels != number of values");
       return NULL;
   }

   if (chancount == -1) {
      if (!output())
         return NULL;
      Py_RETURN_NONE;
   }

   for (i=0; i<chancount; i++) {
      // get channel number
      if (chanlist) {
         if ((tempobj = PyList_GetItem(chanlist, i)) == NULL) {
            return NULL;
         }
      } else { // assume chantuple
         if ((tempobj = PyTuple_GetItem(chantuple, i)) == NULL) {
            return NULL;
         }
      }

#if PY_MAJOR_VERSION >= 3
      if (PyLong_Check(tempobj)) {
         channel = (int)PyLong_AsLong(tempobj);
#else
      if (PyInt_Check(tempobj)) {
         channel = (int)PyInt_AsLong(tempobj);
#endif
         if (PyErr_Occurred())
             return NULL;
      } else {
          PyErr_SetString(PyExc_ValueError, "Channel must be an integer");
          return NULL;
      }

      // get value
      if (valuecount > 0) {
          if (valuelist) {
             if ((tempobj = PyList_GetItem(valuelist, i)) == NULL) {
                return NULL;
             }
          } else { // assume valuetuple
             if ((tempobj = PyTuple_GetItem(valuetuple, i)) == NULL) {
                return NULL;
             }
          }
#if PY_MAJOR_VERSION >= 3
          if (PyLong_Check(tempobj)) {
             value = (int)PyLong_AsLong(tempobj);
#else
          if (PyInt_Check(tempobj)) {
             value = (int)PyInt_AsLong(tempobj);
#endif
             if (PyErr_Occurred())
                 return NULL;
          } else {
              PyErr_SetString(PyExc_ValueError, "Value must be an integer or boolean");
              return NULL;
          }
      }
      if (!output())
         return NULL;
   }

   Py_RETURN_NONE;
}

line number 468

if (PyErr_Occurred())
    return NULL;

checks for errors and silently returns NULL. this might explain why no errors where reported.

  • Thanks for your answer. I tried changing the 1 constant used in place of GPIO.HIGH and it still doesn't work. – prasanth_ntu Sep 30 '16 at 7:45
-1

I checked this program on Raspbian Wheezy(Python 2 and Python3) and Raspbian Jessie(Python2 and Python3). It works very well. I didn't used Keyboard interrupt in this program. From my previous experience Keyboard interrupt put me in trouble. I am now sticking with BCM numbering of Raspberry Pi. The GPIO#12 is GPIO18 according to BCM numbering. We know that we are using while(True) instead while(1) to produce infinite loops. Here we are using True instead 1 or HIGH and False instead 0 or LOW.

import RPi.GPIO as GPIO
import time
while True:
    GPIO.setwarnings(False) # Removing warnings
    GPIO.setmode(GPIO.BCM)
    GPIO.setup(18,GPIO.OUT)
    time.sleep(1)
    GPIO.output(18, True)
    time.sleep(1)
    GPIO.output(18, False)

According to me it is unnecessary to add keyboard interrupt for this one.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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