سؤال

أحاول التحكم في سيارتي Raspberry Pi عبر الاتصال اللاسلكي وwebiopi.تعمل الوظيفة الأساسية بشكل جيد - لديك واجهة حيث أنقر فوق fwd وستتحرك السيارة للأمام وعندما أحرر الزر ستتوقف.

أريد الآن دمج مستشعر المسافة بالموجات فوق الصوتية بحيث عندما أقود السيارة للأمام، يجب أن تتوقف السيارة عندما يكون هناك شيء أمامها.لقد قمت بذلك حيث عندما أنقر على الزر fwd، ستقود السيارة وتتوقف عندما يكون هناك شيء ما في النطاق ولكنها ستتوقف فقط عندما يكون هناك شيء ما في النطاق وليس عندما أحرر الزر.حلقة while الخاصة بي تتكرر بطريقة ما (عالقة) ولا تقرأ وظيفة زر التحرير من webiopi.

هل يمكن لأي شخص أن يساعدني - لقد كنت أقوم بذلك منذ أيام ولست متأكدًا من الخطأ الذي أرتكبه :-(

هذه هي الحلقة من برنامج python النصي الخاص بي:

def go_forward(arg):
  global motor_stop, motor_forward, motor_backward, get_range
  print "Testing"
  print mousefwd()
  while (arg) == "fwd":
      print (arg)
      direction = (arg)
      dist = get_range()
      print "Distance %.1f " % get_range()
      if direction == "fwd" and get_range() < 30:
          motor_stop()
          return
      else:
          motor_forward()

وهنا هو الكود من استدعاء وظيفة webiopi الخاص بي:

 function go_forward() {
              var args = "fwd"
              webiopi().callMacro("go_forward", args);
      }
 function stop1() {
              var args = "stop"
              webiopi().callMacro("go_forward", args);
              webiopi().callMacro("stop");
    }

هذه هي الطريقة التي أستخدمها الآن ولكني ما زلت لا أعمل (أنا مستجد تمامًا :-)) ) :

 def go_forward(arg):
  global motor_stop, motor_forward, motor_backward, get_range
  print "Testing"
  direction = arg
  while direction == "fwd":
      print arg
      dist = get_range()
      print "Distance %.1f " % get_range()
      if get_range() < 30:
         motor_stop()
      elif direction == "fwd":
         motor_forward()
      else:
         motor_stop()

ربما خطوة طفيفة إلى الأمام.تأكد من أن webipi يستخدم "الحلقة" الخاصة به وقمت بإضافة رمز الحلقة للتحقق من حالة GPIO للمحرك والمسافة وإذا كان المحرك يعمل وإذا كانت المسافة قصيرة جدًا فتوقف.تتحرك السيارة الآن عندما أضغط على الزر الأمامي وتتوقف عندما أتركه وعندما تتحرك للأمام وتكون المسافة أقل من 30 سم ستتوقف.المشكلة الوحيدة هي أنه عندما تكون المسافة قصيرة جدًا وأضغط على الزر "إعادة التوجيه بسرعة كبيرة" عدة مرات ، أحصل الآن على "gpio.output (Echo ، 1) _webiopi.gpio.invaliddirection:قناة GPIO ليست خطأ OUTPUT :-( .

يبدو الكود الآن كالتالي:

 def go_forward(direction):
   motor_forward()

 def loop():
   if get_range() < 30 and GPIO.digitalRead(M1) == GPIO.HIGH:
     stop()
     print "stop"
   sleep(1)
هل كانت مفيدة؟

المحلول

سأجيب على مشكلتك الرئيسية في دقيقة واحدة، ولكن أولاً أريد أن أذكر شيئًا تفعله كمبتدئ في لغة بايثون، وهو ما يجعل حياتك أكثر تعقيدًا مما ينبغي.

ليست هناك حاجة ل global البيان الذي لديك في بداية وظيفتك.في بايثون، ما عليك سوى استخدام global بيان إذا كنت تريد يكتب إلى متغير عالمي.إذا كان كل ما عليك فعله هو يقرأ المتغير، أو استدعاء الدالة، ثم ليست هناك حاجة ل global إفادة.سيتم البحث عن أي أسماء مستخدمة في وظيفتك، سواء كانت أسماء متغيرات أو أسماء دوال، بالترتيب التالي:محلي، مغلق، عالمي، مدمج."محلي" يعني الأسماء المحددة داخل وظيفتك، مثل your direction عامل."الإحاطة" هي قاعدة تستخدم عند تعريف دالة داخل دالة أخرى.يعد هذا مفيدًا في العديد من المواقف، ولكنه موضوع متقدم بعض الشيء ولا داعي للقلق بشأنه في الوقت الحالي."عام" يعني أسماء (المتغيرات أو الوظائف أو الفئات) المحددة في المستوى الأعلى لبرنامجك - مثل motor_stop وظيفة من بين أمور أخرى.وأخيرًا، تعني كلمة "builtin" الأسماء المدمجة في لغة Python، مثل str أو int أو file.

لذلك إذا تركت global بيان، ثم ستبحث بايثون عن الاسم motor_stop (وأسماء الوظائف الأخرى) على النحو التالي:

  1. محلي: هل يوجد motor_stop المحددة في هذه الوظيفة؟لا.المضي قدمًا.
  2. أرفق: هل هذه الوظيفة محددة داخل وظيفة أخرى؟لا، لذا فإن قاعدة "الإرفاق" لا تنطبق.المضي قدمًا.
  3. عالمي: هل يوجد motor_stop المحددة في المستوى الأعلى للبرنامج؟نعم.وجدته.
  4. (مدمج):لم يتم التحقق من هذه القاعدة مطلقًا، لأنه تم العثور على الاسم بواسطة القاعدة "العالمية".

يتم تعريف جميع وظائفك في المستوى الأعلى لبرنامجك، وبالتالي فإن القاعدة "العالمية" ستجدها دون الحاجة إلى global إفادة.هذا ينبغي أن يجعل حياتك أسهل قليلا.

والآن بالنسبة لسؤالك الرئيسي:لماذا يتكرر الكود الخاص بك إلى الأبد.وذلك لأن شرط الاختبار الخاص بك while لن تصبح الحلقة كاذبة أبدًا.أنت تقوم بالتكرار while direction == "fwd", والكود الموجود داخل while الحلقة لا تغير أبدًا direction عامل.لذلك في كل مرة تصل إلى نهاية الحلقة، فإنها تعود لاختبار الحالة مرة أخرى.ال direction المتغير لا يزال يحتوي على السلسلة "fwd", ، وهكذا يتم تشغيل حلقة while مرة ثانية.ثم direction المتغير لا يزال يحتوي على السلسلة "fwd", ، وهكذا يتم تشغيله للمرة الثالثة.وهلم جرا وهلم جرا.

طريقة واحدة للخروج while حلقة عندما تريد الخروج سيكون لضبط direction متغير إلى شيء آخر، مثل "stop", ، عندما تريد التوقف.(على سبيل المثال، بعد الاتصال motor_stop()).هناك طريقة أخرى تتمثل في استخدام return بيان للخروج من الوظيفة عند هذه النقطة.لكن اقتراحي سيكون استخدام break البيان بدلاً من ذلك ، مما يعني "في هذه المرحلة ، الخروج على الفور من الحلقة التي أنا فيها." إنه يعمل على كليهما while حلقات و for الحلقات، وهي عبارة مفيدة جدًا يجب معرفتها.يبدو أنك تريد الخاص بك while حلقة للخروج في أي وقت تتصل فيه motor_stop(), ، إذن هناك مكانان يمكنك وضعهما break إفادة:

def go_forward(arg):
  print "Testing"
  direction = arg
  while direction == "fwd":
      print arg
      dist = get_range()
      print "Distance %.1f " % get_range()
      if get_range() < 30:
         motor_stop()
         break
      elif direction == "fwd":
         motor_forward()
         # No break statement here, so the while loop continues
      else:
         motor_stop()
         break

هناك بعض التغييرات الأخرى التي أقترح إجراؤها.أولا، اتصل get_range() ثلاث مرات في حلقتك، لكنك في الحقيقة تحتاج إلى الاتصال بها مرة واحدة فقط.لقد قمت بالفعل بتعيين نتائجها إلى أ dist متغير، فلماذا لا تستخدم هذا المتغير؟

def go_forward(arg):
  print "Testing"
  direction = arg
  while direction == "fwd":
      print arg
      dist = get_range()
      print "Distance %.1f " % dist
      if dist < 30:
         motor_stop()
         break
      elif direction == "fwd":
         motor_forward()
         # No break statement here, so the while loop continues
      else:
         motor_stop()
         break

وثانياً، لا يوجد طريق إلى داخل while حلقة ل direction لا ليكون "fwd"، وبالتالي فإن النهائي else غير ضروري، ويمكن أن تصبح وظيفتك:

def go_forward(arg):
  print "Testing"
  direction = arg
  while direction == "fwd":
      print arg
      dist = get_range()
      print "Distance %.1f " % dist
      if dist < 30:
         motor_stop()
         break
      else:
         motor_forward()

وأخيرًا، لديك معلمة دالة مسماة arg, ، وهو الاسم الذي لا يخبرك شيئًا عن الغرض من استخدامه.يمكنك تعيينه على الفور إلى متغير يسمى direction, ، وهو اسم أفضل بكثير.فلماذا لا تستخدم ذلك كاسم المعلمة في المقام الأول؟لا توجد قاعدة تنص على معلمات الوظيفة يجب يُطلق عليه "arg" ؛يمكن تسميتها بأي شيء تريده (باستثناء إحدى الكلمات المحجوزة في Python مثل break أو if).لذلك دعونا نعطي وظيفتك اسم معلمة أكثر وضوحًا، وهذا من شأنه تبسيطها بشكل أكبر:

def go_forward(direction):
  print "Testing"
  while direction == "fwd":
      print direction
      dist = get_range()
      print "Distance %.1f " % dist
      if dist < 30:
         motor_stop()
         break
      else:
         motor_forward()

هناك.هذا أسهل بكثير في القراءة والفهم، ويجب أن يحل المشكلة التي كنت تراها في جهازك while لا تخرج الحلقة عندما تقترب السيارة كثيرًا من جسم ما.

(لا تزال هناك مشكلة واحدة محتملة يمكنني رؤيتها، وهي أن الحلقة أثناء القيادة قد لا تخرج أثناء قيادة السيارة للأمام، على الرغم من أنك حررت زر "الأمام" - ولكن يجب أن أرى motor_forward() رمز لمعرفة كيفية حل هذا واحد.قد يكون الأمر بسيطًا مثل وضع ملف break بيان بعد motor_forward(), ، وفي هذه الحالة لن تكون هناك حاجة حقًا إلى أ while حلقة على الإطلاق - ولكن يجب أن أعرف كيف motor_forward() يتفاعل الكود مع webiopi وكيفية عمل كود التعامل مع الأحداث الخاص بـ webiopi.لا أعرف أيًا منها الآن، لذا سأجيب على المشكلات التي يمكنني الإجابة عليها الآن حتى لو كانت إجابتي غير كاملة، بدلاً من تركك بدون إجابة على الإطلاق.)

تحرير بواسطة مارك: إليك رمز motor_forward:

 def motor_forward():
     GPIO.output(M1, GPIO.HIGH)
     GPIO.output(M2, GPIO.LOW)
     string = "echo 0=130 > /dev/servoblaster"
     os.system(string)

نصائح أخرى

جرب هذا - تتوقف دائما على المدى ولكن قد ترغب في التوقف عن الاتجاه

giveacodicetagpre.

btw أنت لا تحتاج إلى Arg (Arg) فقط عند الرجوع إليه

طباعة Arg

الشجاعة في توقيع المكالمات موجودة لإظهار لوحة لها وظيفة

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top