Skip to content

Commit

Permalink
Merge remote-tracking branch 'refs/remotes/origin/main'
Browse files Browse the repository at this point in the history
  • Loading branch information
ErikUmble committed May 16, 2024
2 parents a857636 + 1e22027 commit fa4f3de
Show file tree
Hide file tree
Showing 18 changed files with 320 additions and 42 deletions.
51 changes: 51 additions & 0 deletions docs/source/#movement.rst#
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
.. _Movement:

Movement
=========
Working with NanoNav's motors.

Introduction
------------

To complete the Wumpus challenge, NanoBot will have to navigate the board by moving and turning. It does this by sending power to the motors, which then turn the wheels. Speed of the motors is controlled by the amount of power you send. However, because most microcontrollers can only send LOW or HIGH voltage (0V or 3.3V in the Arduino's case), power is controlled by a process called Pulse Width Modulation (PWM), which is explained in more detail `here <https://learn.sparkfun.com/tutorials/pulse-width-modulation/all>`_ if you're interested.

Sensors called encoders are used to track the rotation of the motors accurately. Encoders track rotation in ticks. You can read more `here <https://howtomechatronics.com/tutorials/arduino/rotary-encoder-works-use-arduino/>`_ if you're interested, but all you have to know is that a positive change in ticks corresponds to a forward rotation of the motor, and a negative change to a backward rotation of the motor.

You don't have to use encoders in your solution, though they do provide greater accuracy.


Quick Example
-------------

.. code-block:: python

from nanonav import NanoBot
import time

# Create a NanoBot object
robot = NanoBot()

# Move forward for 2 seconds
robot.m1_forward(30)
robot.m2_forward(30)
time.sleep(2)

# Stop
robot.stop()
robot.sleep(2)

# Move backward for 2 seconds
robot.m1_backward(30)
robot.m2_backward(30)
time.sleep(2)

# Stop
robot.stop()

Usage
-----

.. autoclass:: nanonav.NanoBot
:members:
:exclude-members: ir_left, ir_right

1 change: 1 addition & 0 deletions docs/source/.#movement.rst
4 changes: 3 additions & 1 deletion docs/source/bluetooth.rst
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ Quick Example
.. code-block:: python
from nanonav import BLE
import time
# Create a Bluetooth object
ble = BLE(name="NanoNav")
Expand All @@ -19,6 +20,7 @@ Quick Example
# wait until something changes, indicating a response
while response == 43:
response = ble.read()
time.sleep(0.5)
print("Received: ", response)
Expand Down Expand Up @@ -67,4 +69,4 @@ above picture, you can click the :blue:`Read Again` button as often as you would
change when you (or NanoNav) writes to it. And you can send a number as often as you want in LightBlue, but NanoNav will not know unless you program it to
read the value periodically. (Actually, you can setup BLE interrupts for NanoNav to run code when something changes in the BLE connection, similar to the :py:meth:`~nanonav.BLE.on_connected` and :py:meth:`~nanonav.BLE.on_disconnected`, but we think
you'll have an easier time getting your code to work as expected by avoiding that kind of programming for now).
If interested in learning about other bluetooth capabilities beyond the scope of NanoNav, see `here <https://docs.micropython.org/en/latest/library/bluetooth.html>`_.
If interested in learning about other bluetooth capabilities beyond the scope of NanoNav, see `here <https://docs.micropython.org/en/latest/library/bluetooth.html>`_.
21 changes: 20 additions & 1 deletion docs/source/faq.rst
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,27 @@ FAQ

No questions yet.

Troubleshooting
===============

Arduino not connecting to OpenMV
--------------------------------

If your Arduino is not connecting to OpenMV, either because OpenMV is loading forever, or because the cursor is flickering between loading and a pointer, you should reset your board. Do this by double tapping the button on top of the Arduino. This will reset the board. Wait for OpenMV to update. When OpenMV updates, it should offer to load the latest firmware. Agree and load the firmware, and hopefully the Arduino will connect.

If this doesn't work, it's probably because your code has a frequently repeating while loop which keeps the Arduino occupied. Keep trying to reset the board by double pressing the top button, or open Finder or FileExplorer, open the board's external drive, and replace its main.py (your code) with a basic main.py such as :download:`blink_LED.py <../../tests/installation_check/blink_LED.py>`. This should enable the Arduino to connect.

If you still cannot get the Arduino to connect, it could be a problem on your computer. Try changing the port you're using to connect to the Arduino.

Strange problems with code which was just working
-------------------------------------------------

When you run in laptop mode from OpenMV, sometimes the code gives you errors the first 2 times you try to run. We're not sure why this happens, but these errors always go away after the third attempt.

If when running in solo mode, the Arduino behaves strangely when running code which you know works, it could be because you are out of storage. This will not happen until your code files are at least 30 KB in total!!! If your code files are not 30 KB or larger in total, what you're experiencing is an ordinary bug. If you suspect that you make be out of storage, try to shrink your code by removing comments and making functions more efficient. Every character counts, because it's the storage of your .py files which is running out. Try removing excess newlines or whitespace.

Issues
------

Found a bug? Create an issue on GitHub. Submit `here <https://github.com/Bram-Hub/NanoNav/issues>`_ with as much information as you can provide
about the context of the bug.
about the context of the bug.
Binary file added docs/source/images/IR_assembled.jpeg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added docs/source/images/openmv_green.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added docs/source/images/openmv_running.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added docs/source/images/openmv_unconnected.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added docs/source/images/parts.jpeg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added docs/source/images/top_view.jpeg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added docs/source/images/wheels.jpeg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
34 changes: 32 additions & 2 deletions docs/source/movement.rst
Original file line number Diff line number Diff line change
Expand Up @@ -4,18 +4,48 @@ Movement
=========
Working with NanoNav's motors.

Introduction
------------

To complete the Wumpus challenge, NanoBot will have to navigate the board by moving and turning. It does this by sending power to the motors, which then turn the wheels. Speed of the motors is controlled by the amount of power you send. However, because most microcontrollers can only send LOW or HIGH voltage (0V or 3.3V in the Arduino's case), power is controlled by a process called Pulse Width Modulation (PWM), which is explained in more detail `here <https://learn.sparkfun.com/tutorials/pulse-width-modulation/all>`_ if you're interested.

Sensors called encoders are used to track the rotation of the motors accurately. Encoders track rotation in ticks. You can read more `here <https://howtomechatronics.com/tutorials/arduino/rotary-encoder-works-use-arduino/>`_ if you're interested, but all you have to know is that a positive change in ticks corresponds to a forward rotation of the motor, and a negative change to a backward rotation of the motor.

You don't have to use encoders in your solution, though they do provide greater accuracy.


Quick Example
-------------

.. code-block:: python
from nanonav import ...
from nanonav import NanoBot
import time
# Create a NanoBot object
robot = NanoBot()
# Move forward for 2 seconds
robot.m1_forward(30)
robot.m2_forward(30)
time.sleep(2)
# Stop
robot.stop()
robot.sleep(2)
# TODO
# Move backward for 2 seconds
robot.m1_backward(30)
robot.m2_backward(30)
time.sleep(2)
# Stop
robot.stop()
Usage
-----

.. autoclass:: nanonav.NanoBot
:members:
:exclude-members: ir_left, ir_right

96 changes: 70 additions & 26 deletions docs/source/nanonav.py
Original file line number Diff line number Diff line change
Expand Up @@ -62,9 +62,9 @@ class NanoBot:
"""
Interact with Arduino and peripheral hardware for movement and sensing.
:param saturated_duty: The maximum duty cycle to use for the motors. This can be increased to compensate somewhat for lower battery voltage.
:param saturated_speed: The maximum duty cycle to use for the motors. This is a percentage of max speed the motor can supply from 0-100. If you find that your NanoBot is driving too fast or not driving fast enough, try changing this value.
"""
def __init__(self, saturated_duty=22000, *args, **kwargs):
def __init__(self, saturated_speed=33, *args, **kwargs):

# turn ir sensor pin on (inactive because it's active low)
self.ir_right_sensor = Pin(28, Pin.OUT)
Expand Down Expand Up @@ -92,7 +92,7 @@ def __init__(self, saturated_duty=22000, *args, **kwargs):

# initialize motor constants
self.max_duty = 65535 # constant
self.saturated_duty = saturated_duty # choice for max speed
self.saturated_duty = saturated_duty * self.max_duty / 100 # choice for max speed
assert(0 <= self.saturated_duty <= self.max_duty)
self.turn90ticks = 120
self.turn_error = 5
Expand Down Expand Up @@ -143,33 +143,41 @@ def enc_pin_high(self, pin):
def calc_duty(self, duty_100):
return int(duty_100 * self.max_duty / 100)

def m1_forward(self, duty_cycle):
self.m1pwm1.duty_u16(min(self.calc_duty(duty_cycle), self.saturated_duty))
self.m1pwm2.duty_u16(0)
def m1_forward(self, speed):
"""
Set Motor 1 to turn forward at speed.
def m2_backward(self, duty_cycle):
self.m1pwm1.duty_u16(0)
self.m1pwm2.duty_u16(min(self.calc_duty(duty_cycle), self.saturated_duty))
:param speed: The speed to turn Motor 1 forward at. This is a percentage of max speed from 0-100.
:type speed: int or float
"""
pass

def m1_signed(self, duty_cycle):
if duty_cycle >= 0:
self.m1_forward(duty_cycle)
else:
self.m2_backward(-duty_cycle)
def m2_backward(self, speed):
"""
Set Motor 1 to turn backward at speed.
:param speed: The speed to turn Motor 1 backward at. This is a percentage of max speed from 0-100.
:type speed: int or float
"""
pass

def m2_forward(self, duty_cycle):
self.m2pwm1.duty_u16(min(self.calc_duty(duty_cycle), self.saturated_duty))
self.m2pwm2.duty_u16(0)
def m2_forward(self, speed):
"""
Set Motor 2 to turn forward at speed.
def m2_backward(self, duty_cycle):
self.m2pwm1.duty_u16(0)
self.m2pwm2.duty_u16(min(self.calc_duty(duty_cycle), self.saturated_duty))
:param speed: The speed to turn Motor 2 forward at. This is a percentage of max speed from 0-100.
:type speed: int or float
"""
pass

def m2_backward(self, speed):
"""
Set Motor 2 to turn backward at speed.
def m2_signed(self, duty_cycle):
if duty_cycle >= 0:
self.m2_forward(duty_cycle)
else:
self.m2_backward(-duty_cycle)
:param speed: The speed to turn Motor 2 backward at. This is a percentage of max speed from 0-100.
:type speed: int or float
"""
pass

def stop(self):
"""
Expand All @@ -180,11 +188,47 @@ def stop(self):
def ir_left(self):
"""
Return true if the left IR sensor detects white.
:rtype: boolean
"""
pass

def ir_right(self):
"""
Return true if the right IR sensor detects white.
:rtype: boolean
"""
pass

def get_enc1(self):
"""
Return the current encoder 1 count.
:return: The value of the encoder 1.
:rtype: int
"""

def get_enc2(self):
"""
Return the current encoder 2 count.
:return: The value of the encoder 2.
:rtype: int
"""

def set_enc1(self, value):
"""
Set the current encoder 1 count. This is useful if you want to zero its value.
:param value: The new value to set the encoder 1 count to.
:type value: int
"""

def set_enc2(self, value):
"""
Set the current encoder 2 count. This is useful if you want to zero its value.
:param value: The new value to set the encoder 2 count to.
:type value: int
"""
pass
8 changes: 7 additions & 1 deletion docs/source/sensors.rst
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,10 @@
Sensors
=======

To best interact with its environment, your NanoNav kit comes with infrared sensors that can be used for detecting how reflective the surface under it is.
To best interact with its environment, your NanoNav kit comes with infrared sensors that can be used for detecting how reflective the surface under it is.

Usage
-----

.. autoclass:: nanonav.NanoBot
:members: ir_left, ir_right
Loading

0 comments on commit fa4f3de

Please sign in to comment.