1
1
forked from MDL29/JacoBot
This commit is contained in:
Linux_Hat 2024-04-23 19:36:16 +02:00
parent 51545da322
commit edbb697b29
33 changed files with 232 additions and 336 deletions

View File

@ -1,88 +0,0 @@
// Made by Linux_Hat
#include "Car.h"
#include "MotorEncoder.h"
#define pi 3.1415
Car::Car(MotorEncoder* m1, MotorEncoder* m2, float distance)
: m_m1(m1), m_m2(m2), m_distance(distance) {
}
void Car::forward(float distance, double setPoint) { //distance : mm
const float m1_mmp = pi*(*m_m1).m_radius*2/(*m_m1).m_ratio; // mm/pulse for m1
const float m2_mmp = pi*(*m_m2).m_radius*2/(*m_m2).m_ratio; // mm/pulse for m2
double m1_duration = 0;
double m2_duration = 0;
m_m1->setPoint = setPoint;
m_m2->setPoint = setPoint/m2_mmp*m1_mmp;
while(m1_duration<distance/m1_mmp && m2_duration<distance/m2_mmp) {
if(m1_duration<distance/m1_mmp) {
m1_duration+=m_m1->duration;
m_m1->compute(0);
m_m1->advance();
m_m1->duration = 0;
} else {m_m1->stop();}
if(m2_duration<distance/m2_mmp) {
m2_duration+=m_m2->duration;
m_m2->compute(0);
m_m2->advance();
m_m2->duration = 0;
} else {m_m2->stop();}
}
m_m1->stop();
m_m2->stop();
}
void Car::turn(float angle, double setPoint) { //angle : degre
float distance = pi*m_distance/360*angle;
const float m1_mmp = pi*(*m_m1).m_radius*2/(*m_m1).m_ratio; // mm/pulse for m1
const float m2_mmp = pi*(*m_m2).m_radius*2/(*m_m2).m_ratio; // mm/pulse for m2
double m1_duration = 0;
double m2_duration = 0;
m_m1->setPoint = setPoint;
m_m2->setPoint = setPoint/m2_mmp*m1_mmp;
boolean m1_tmp = false;
boolean m2_tmp = false;
if(angle>0) {
while(!m1_tmp && !m2_tmp) {
if(m1_duration<distance/m1_mmp) {
// Serial.print("M1 cycle ");
// Serial.print(m1_duration);
// Serial.print(" ");
// Serial.println(m_m1->duration);
m1_duration+=m_m1->duration;
m_m1->compute(0);
m_m1->advance();
m_m1->duration = 0;
} else {m1_tmp = true; m_m1->stop();}
if(m2_duration<distance/m2_mmp) {
// Serial.print("M2 cycle ");
// Serial.print(m2_duration);
// Serial.print(" ");
// Serial.println(m_m2->duration);
m2_duration-=m_m2->duration;
m_m2->compute(0);
m_m2->back();
m_m2->duration = 0;
} else {m2_tmp = true; m_m2->stop();}
}
} else if(angle<0) {
while(!m1_tmp && !m2_tmp) {
if(m1_duration<distance/m1_mmp) {
m1_duration-=m_m1->duration;
m_m1->compute(0);
m_m1->back();
m_m1->duration = 0;
} else {m1_tmp = true; m_m1->stop();}
if(m2_duration<distance/m2_mmp) {
m2_duration+=m_m2->duration;
m_m2->compute(0);
m_m2->advance();
m_m2->duration = 0;
} else {m2_tmp = true; m_m2->stop();}
}
}
Serial.println(m1_tmp);
Serial.println("End");
m_m1->stop();
m_m2->stop();
}

View File

@ -1,14 +0,0 @@
// Made by Linux_Hat
#pragma once
#include "MotorEncoder.h"
class Car {
private:
float m_distance;// mm
MotorEncoder* m_m1;
MotorEncoder* m_m2;
public:
Car(MotorEncoder* m1, MotorEncoder* m2, float distance);
void forward(float distance, double setPoint);
void turn(float angle, double setPoint);
};

View File

@ -1,74 +0,0 @@
// Made by Linux_Hat
#include <PID_v1.h>
#include <Arduino.h>
#include "MotorEncoder.h"
MotorEncoder::MotorEncoder(uint8_t encoder0pinA, uint8_t encoder0pinB, int E_left, int M_left, boolean orientation, float ratio, float radius) {
m_encoder0pinA = encoder0pinA; // pin 2 or 3
m_encoder0pinB = encoder0pinB;
m_E_left = E_left;// pwm pin !
m_M_left = M_left;
m_orientation = orientation;
m_ratio = ratio;
m_radius = radius;
setPoint = 0;
pinMode(m_encoder0pinB, INPUT);
pinMode(m_M_left, OUTPUT); // L298P Control port settings DC motor driver board for the output mode
pinMode(m_E_left, OUTPUT);
// Initialize PID controller
myPID = new PID(&abs_duration, &val_output, &setPoint, Kp, Ki, Kd, DIRECT);
myPID->SetMode(AUTOMATIC); // PID is set to automatic mode
myPID->SetSampleTime(100); // Set PID sampling frequency to 100ms
}
void MotorEncoder::wheelSpeed() {
int Lstate = digitalRead(m_encoder0pinA);
if((encoder0PinALast == LOW) && Lstate==HIGH){
int val = digitalRead(m_encoder0pinB);
if(val == HIGH){
if(!m_orientation) duration--;
else duration++;
}
else if(val == LOW){
if(!m_orientation) duration++;
else duration--;
}
}
encoder0PinALast = Lstate;
}
void MotorEncoder::EncoderHandlerInit(void (*ISR)(void)) {
pinMode(m_encoder0pinB, INPUT); // Ensure encoder pin A is set as INPUT
attachInterrupt(m_encoder0pinA-2, ISR, CHANGE);
}
void MotorEncoder::advance() {
digitalWrite(m_M_left, LOW);
analogWrite(m_E_left, abs(val_output));
}
void MotorEncoder::back() {
digitalWrite(m_M_left, HIGH);
analogWrite(m_E_left, abs(val_output));
}
void MotorEncoder::stop() {
analogWrite(m_E_left, 0);
}
void MotorEncoder::compute(int debug) {
abs_duration = abs(duration);
result = myPID->Compute();
if (result) {
if (debug) {
Serial.print("Pluse: ");
Serial.print(duration);
Serial.print(" Power: ");
Serial.println(val_output);
}
duration = 0;
}
}

View File

@ -1,34 +0,0 @@
// Made by Linux_Hat
#pragma once
#include <PID_v1.h>
#include <Arduino.h>
class MotorEncoder {
private:
uint8_t encoder0PinALast; //the number of the pulses
boolean m_orientation; //the rotation orientation
boolean result;
PID* myPID;
double val_output; //Power supplied to the motor PWM value.
double Kp = 0.6, Ki = 5, Kd = 0;
uint8_t m_encoder0pinA; //A pin
uint8_t m_encoder0pinB; //B pin
int m_E_left; //The enabling of L298PDC motor driver board connection to the digital interface port 5
int m_M_left;
double abs_duration;
public:
double setPoint;
float m_ratio; // how many pulse for a complete turn
float m_radius; // wheel radius in mm
double duration;
MotorEncoder(uint8_t encoder0pinA, uint8_t encoder0pinB, int E_left, int M_left, boolean orientation, float ratio, float radius);
void EncoderHandlerInit(void (*ISR)(void));
void wheelSpeed();
void advance();
void back();
void stop();
void compute(int debug);
};

View File

@ -1 +0,0 @@
# JacoBot Arduino

View File

@ -1,30 +0,0 @@
// Made by Linux_Hat
#include <RF24.h>
#include <SPI.h>
#include <Arduino.h>
#include "Radio.h"
#define tunnel "PIPE1"
Radio::Radio(int canal, int pinCE, int pinCSN) {
m_canal = canal;
m_pinCE = pinCE;
m_pinCSN = pinCSN;
radio = new RF24(m_pinCE, m_pinCSN);
if (!radio->begin()) {
Serial.println("Error while initialise the NRF module");
while (1);
}
Serial.println("Module initialised");
radio->openReadingPipe(0, (uint8_t*)tunnel);
radio->setChannel(m_canal);
radio->setPALevel(RF24_PA_MIN);
radio->startListening();
}
char Radio::read() {
if (radio->available()) {
radio->read(&message, sizeof(message));
return *message;
}
return 0;
}

View File

@ -1,17 +0,0 @@
// Made by Linux_Hat
#pragma once
#include <RF24.h>
#include <SPI.h>
#include <Arduino.h>
class Radio {
public:
char* message;
Radio(int canal, int pinCE, int pinCSN);
char read();
private:
int m_canal;
int m_pinCE;
int m_pinCSN;
RF24* radio;
};

View File

@ -1,33 +0,0 @@
// Made by Linux_Hat
#include <Arduino.h>
#include "Radio.h"
#include "MotorEncoder.h"
#include "Car.h"
MotorEncoder m1(2, A4, 5, 4, false, 120, 3.3); // Initialise motor with pins
MotorEncoder m2(3, 9, 10, 8, true, 120, 3.3); // Initialise motor with pins
void encoder_handler_m1() {
m1.wheelSpeed(); // Call wheelSpeed() of the m1 MotorEncoder instance
}
void encoder_handler_m2() {
m2.wheelSpeed(); // Call wheelSpeed() of the m2 MotorEncoder instance
}
//Radio radio(120, 6, 7);
Car car(&m1, &m2, 110); // Initialise the car with motors and distance
void setup() {
Serial.begin(9600);//Initialize the serial port
m1.EncoderHandlerInit(encoder_handler_m1);
m2.EncoderHandlerInit(encoder_handler_m2);
Serial.println("Car started");
car.turn(90, 20);
//car.forward(100,50);
}
void loop() {
}

Binary file not shown.

View File

@ -1,27 +0,0 @@
#include <RF24.h>
#include <SPI.h>
#include <Arduino.h>
#include "radio.h"
Radio::Radio(int canal, int pinCE, int pinCSN) {
m_canal = canal;
m_pinCE = pinCE;
m_pinCSN = pinCSN;
radio = new RF24(pinCE, pinCSN);
if (!radio->begin()) {
Serial.println("Error while initialise the NRF module");
while (1);
}
Serial.println("Module initialised");
radio->openReadingPipe(0, adresse);
radio->setChannel(canal);
radio->setPALevel(RF24_PA_MIN);
radio->startListening();
}
char Radio::read() {
if (radio->available()) {
radio->read(&message, sizeof(message));
return *message;
}
}

View File

@ -1,18 +0,0 @@
#pragma once
#include <RF24.h>
#include <SPI.h>
#include <Arduino.h>
#define tunnel "PIPE1"
class Radio {
public:
Radio(int canal, int pinCE, int pinCSN);
char read();
char message[32];
private:
int m_canal;
int m_pinCE;
int m_pinCSN;
RF24* radio;
const byte adresse[6] = tunnel;
};

View File

@ -0,0 +1 @@
# JacoVirt

Binary file not shown.

After

Width:  |  Height:  |  Size: 455 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 412 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 24 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 42 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 23 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 23 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 23 KiB

View File

@ -0,0 +1,160 @@
import turtle
from importlib import resources
import math
from time import sleep
import redis
r = redis.Redis(host="localhost")
mobile = r.pubsub()
mobile.subscribe('jacobot-instructions')
poscubettox = 0
poscubettoy = 0
xstart = 0
ystart = 0
xmax = 5
ymax = 5
distance = 0
angle = 0
theme = 0
def main():
def dark_theme():
global posxstart, posystart, distance, theme
with resources.path("jacovirt", 'Img') as img_folder :
turtle.bgpic(str(img_folder/ "bot" / "background" / "Background_dark.png"))
turtle.shape(str(img_folder/ "bot" / "cubetto" /"Cubetto_forme_droite_dark.gif"))
turtle.shapesize(3,3,6)
distance = 84
posxstart = -211
posystart = 200
theme = 1
def light_theme():
global posxstart, posystart, distance, theme
with resources.path("jacovirt", 'Img') as img_folder :
turtle.bgpic(str(img_folder/ "bot" / "background" / "Background_light.png"))
turtle.shape(str(img_folder/ "bot" / "cubetto" /"Cubetto_forme_droite_light.gif"))
turtle.shapesize(10,10,6)
distance = 90
posxstart = -226
posystart = 225
theme = 2
def cubetto_init():
global posxstart, posystart, distance
with resources.path("jacovirt", 'Img') as img_folder :
turtle.register_shape(str(img_folder/ "bot" / "cubetto" /"Cubetto_forme_haut_dark.gif"))
turtle.register_shape(str(img_folder/ "bot" / "cubetto" /"Cubetto_forme_bas_dark.gif"))
turtle.register_shape(str(img_folder/ "bot" / "cubetto" /"Cubetto_forme_gauche_dark.gif"))
turtle.register_shape(str(img_folder/ "bot" / "cubetto" /"Cubetto_forme_droite_dark.gif"))
turtle.register_shape(str(img_folder/ "bot" / "cubetto" /"Cubetto_forme_haut_light.gif"))
turtle.register_shape(str(img_folder/ "bot" / "cubetto" /"Cubetto_forme_bas_light.gif"))
turtle.register_shape(str(img_folder/ "bot" / "cubetto" /"Cubetto_forme_gauche_light.gif"))
turtle.register_shape(str(img_folder/ "bot" / "cubetto" /"Cubetto_forme_droite_light.gif"))
dark_theme()
turtle.penup()
turtle.goto(posxstart, posystart)
def cubetto_forme_init():
global angle, theme
with resources.path("jacovirt", 'Img') as img_folder :
if angle == 360 or angle == -360:
angle=0
if angle == 0:
if theme == 1:
turtle.shape(str(img_folder/ "bot" / "cubetto" /"Cubetto_forme_droite_dark.gif"))
elif theme == 2:
turtle.shape(str(img_folder/ "bot" / "cubetto" /"Cubetto_forme_droite_light.gif"))
if angle == 90 or angle == -270:
if theme == 1:
turtle.shape(str(img_folder/ "bot" / "cubetto" /"Cubetto_forme_haut_dark.gif"))
elif theme == 2:
turtle.shape(str(img_folder/ "bot" / "cubetto" /"Cubetto_forme_haut_light.gif"))
if angle == 180 or angle == -180:
if theme == 1:
turtle.shape(str(img_folder/ "bot" / "cubetto" /"Cubetto_forme_gauche_dark.gif"))
elif theme == 2:
turtle.shape(str(img_folder/ "bot" / "cubetto" /"Cubetto_forme_gauche_light.gif"))
if angle == 270 or angle == -90:
if theme == 1:
turtle.shape(str(img_folder/ "bot" / "cubetto" /"Cubetto_forme_bas_dark.gif"))
elif theme == 2:
turtle.shape(str(img_folder/ "bot" / "cubetto" /"Cubetto_forme_bas_light.gif"))
def cubetto_forward():
global xmax, ymax, xstart, ystart, distance, poscubettox, poscubettoy
FuturXRight = (poscubettox+1)
FuturXLeft = (poscubettox-1)
FuturYTop = (poscubettoy-1)
FuturYBottom = (poscubettoy+1)
turtle.forward(distance)
if angle == 0 and FuturXRight <= xmax:
poscubettox += 1
elif (angle == 90 or angle == -270) and FuturYTop >= ystart:
poscubettoy -= 1
elif (angle == 180 or angle == -180) and FuturXLeft >= xstart:
poscubettox -= 1
elif (angle == 270 or angle == -90) and FuturYBottom <= ymax:
poscubettoy += 1
else:
print("You are out of the carpet !")
exit()
def cubetto_left():
global angle
turtle.left(90)
angle += 90
cubetto_forme_init()
def cubetto_right():
global angle
turtle.right(90)
angle -= 90
cubetto_forme_init()
cubetto_init()
while True:
for m_recu in mobile.listen():
if m_recu:
m_data = m_recu["data"]
if m_data == b"FORWARD":
cubetto_forward()
elif m_data == b"LEFT":
cubetto_left()
elif m_data == b"RIGHT":
cubetto_right()
elif m_data == b"INIT":
cubetto_init()
elif m_data == b"EXIT":
exit()
sleep(0.3)
main()

View File

@ -0,0 +1,48 @@
import arcade
# Screen title and size
SCREEN_TITLE = "Jaco Pad"
SCREEN_MULTILPLIER = 1
SCREEN_WIDTH = int(1000* SCREEN_MULTILPLIER)
SCREEN_HEIGHT = int(1000* SCREEN_MULTILPLIER)
# Window color
BACKGROUND_COLOR = (133, 100, 100)
class Pad(arcade.Window):
"""Main application class"""
def __init__(self):
# Init parent class
super().__init__(int(SCREEN_WIDTH), int(SCREEN_HEIGHT), SCREEN_TITLE)
# Set background color
arcade.set_background_color(BACKGROUND_COLOR)
def setup(self):
"""Set up the pad"""
...
def on_draw(self):
"""Render the screen"""
# Clear the screen
self.clear()
def on_key_press(self, symbol, modifiers):
"""Called when the user presses key"""
if symbol == arcade.key.R:
self.setup()
print("Restart !")
if symbol == arcade.key.Q:
arcade.exit()
def main():
"""Main method"""
window = Pad()
window.setup()
arcade.run()

23
jacovirt/pyproject.toml Normal file
View File

@ -0,0 +1,23 @@
[tool.poetry]
name = "jacovirt"
version = "0.1.0"
description = ""
authors = ["LPH"]
readme = "README.md"
[tool.poetry.dependencies]
python = "^3.11"
arcade = "^2.6.17"
redis = "^5.0.3"
[build-system]
requires = ["poetry-core"]
build-backend = "poetry.core.masonry.api"
[tool.poetry.scripts]
jacovirt-bot = "jacovirt.jacobot:main"
jacovirt-pad = "jacovirt.pad.window:main"
[[tool.poetry.include]]
path = "jacovirt/jacovirt/Img/*"

View File