Mechanical Design, Machine Design
make machine in group
Intro.
Hey! welcome to machine week. This week me and my fablab group will work together to make working machine. We dont have Individual assignment but Individual job to do here according to our skill set.
Week Task:
group assignment
- design a machine that includes mechanism+actuation+automation
- build the mechanical parts and operate it manually
- document the group project and your individual contribution
Firmware,Interface and comminucation
Machines are not just mechanical parts of something. It is combination of electronic, software and everthing that make it work
In group project I am looking after Software part like firmware, Interface and comminucation protocol.
we plan to build CNC sketching Car we named it कलाCar (कला mean Art). Since most of CNC machines like 3D printer, lasercutter ,vinyl cutter etc are limiter to it bed sizes. This also make them huge in overall size. So we plan to make CNC bot to be free from bed size so it can draw on any size canvas. Sketching Car is fun but real motive is came after knowing it vash application even in farming. But lets not to complicated things now
Structure and electronics:
KalaCar is two wheel sketching robot. Two wheel are drive using nema 17 stepper motors. Wheel parts designing and developing was done by Anand Tale
It draw with a marker on reponse at Z axis. It work on servo motor and design for Z axis mechanism was Done by pavan kuchar
It work using Arduino mega. For driving different output devices like stepper motors and servo We have used RAMPS sheild for Mega. We added battery pack to make our project completely wireless it communicate through bluetooth This Job was Detail by Vijay Karale .
Since everyone of us was new in this kind of work so it not that they only done all that jobs all alone each one of us helping and sharing his expertise.
Mohit ahuja took responsility to combining all part and supporting people on troubleshooting.
Fab X student Pradeep Kumar was young member of group supported everyone in work and provided all help needed
we have two week to complete this project so first week spent on structure and on all assembly so remaining one week was my responsility to perpare firmware and interface
Blender Script and Python
Blender is OpenSource 3D modeling and animation Software. Mostly like many other Softwares Blender can be Control and Program via text and that called Script. Blender Script is in Python Language so possibility of experimenting is huge
We agreed to use blender for our interface part. Blender is well developed application hence perfect for our use.
So this is not the first code I started with but code I made after some failed experiments. Some maybe not true you can say many that I missed to document each thing because I was too much busy with writing and solving logic on code.
Since whatever I have done to come this much far have worth it
So first let me share some chanllenges and useful finding before moving on codes
After some long study and experiment I observe that when normal script or python code runs through blender It freeze the whole interface until background script get his job done else if code is loop in nature it keep running and UI stay freeze and In that case you need to terminate whole blender Program
I have use timing event which trigger function having a code to move timeframe one step ahead on every interval of time until it complete the total number of frames.
There is 3d object in viewport that can animated manually or by attaching it with path with respect to timeline.
On each frame object move or change it positions because it been animated. So what script does is that it take each updated location value and send it through bluetooth serial communication to the car and car response accordingly to the value it received
This stay continue until it reached to it last frame
* Here is Final Blender Script
import bpy
import serial
import time
import os
import math
from bpy.props import EnumProperty
from bpy.types import Operator, Panel
from bpy.utils import register_class, unregister_class
ser = serial.Serial('COM22', 9600)
time.sleep(2) # wait for the serial connection to initialize
con="happy"
#--------------------------------------------------------------------------------------------------
class ModalTimerOperator(bpy.types.Operator):
"""Operator which runs its self from a timer"""
bl_idname = "wm.modal_timer_operator"
bl_label = "Modal Timer Operator"
_timer = None
def modal(self, context, event):
if event.type in {'RIGHTMOUSE', 'ESC'}:
self.cancel(context)
return {'CANCELLED'}
if event.type == 'TIMER':
global con
if bpy.context.scene.frame_current < bpy.context.scene.frame_end :
bpy.context.scene.frame_set(bpy.context.scene.frame_current + 1)
xt,yt,zt = bpy.context.object.matrix_world.to_translation()
xr,yr,zr = bpy.context.object.matrix_world.to_euler()
step = bpy.context.object.constraints["Follow Path"].offset_factor * 300
while con != b'start\r\n':
ser.write(str(123.321).encode())
con = ser.readline()
con='0'
print("started")
time.sleep(0.1)
ser.write(str(step).encode())
con = ser.readline()
while con != b'dones\r\n':
con = ser.readline()
con='0'
print(step)
time.sleep(0.1)
ser.write(str(math.degrees(zr)).encode())
con = ser.readline()
while con != b'doner\r\n':
con = ser.readline()
con='0'
print(math.degrees(zr))
time.sleep(0.1)
ser.write(str(zt).encode())
con = ser.readline()
while con != b'donez\r\n':
con = ser.readline()
con='0'
print(zt)
print("Data Send \n")
con = ser.readline()
while con != b'done\r\n':
con = ser.readline()
con='0'
print("Data excuted \n")
else:
# change theme color, silly!
color = context.preferences.themes[0].view_3d.space.gradients.high_gradient
color.s = 1.0
color.h += 0.01
return {'PASS_THROUGH'}
def execute(self, context):
wm = context.window_manager
self._timer = wm.event_timer_add(0.1, window=context.window)
wm.modal_handler_add(self)
return {'RUNNING_MODAL'}
def cancel(self, context):
wm = context.window_manager
wm.event_timer_remove(self._timer)
#--------------------------------------------------------------------------------------------------
class TEST_PT_panel(Panel):
bl_idname = 'TEST_PT_panel'
bl_label = 'Test'
bl_space_type = 'VIEW_3D'
bl_region_type = 'UI'
bl_category = 'Test'
def draw(self, context):
layout = self.layout
layout.operator('test.test_op', text='Reset completely').action = 'HM'
layout.operator('test.test_op', text='start streaming').action = 'RF'
layout.operator('test.test_op', text='Disconnect serial').action = 'DC'
#--------------------------------------------------------------------------------------------------
class TEST_OT_test_op(Operator):
bl_idname = 'test.test_op'
bl_label = 'Test'
bl_description = 'Test'
bl_options = {'REGISTER', 'UNDO'}
action: EnumProperty(
items=[
('HM', 'Home', 'Home'),
('RF', 'Refresh', 'Refresh'),
('DC', 'Disconnect', 'Disconnect')
]
)
def execute(self, context):
if self.action == 'HM':
self.reset_scene(context=context)
elif self.action == 'RF':
self.start_trans(context=context)
elif self.action == 'DC':
self.disconnect_port(context=context)
return {'FINISHED'}
@staticmethod
def reset_scene(context):
print("1")
# Define the serial port and baud rate.
bpy.ops.object.select_all(action='SELECT')
bpy.ops.object.delete(use_global=False, confirm=False)
bpy.ops.mesh.primitive_cube_add(location=(0, 0, 0))
@staticmethod
def start_trans(context):
print("sending...")
bpy.ops.wm.modal_timer_operator()
@staticmethod
def disconnect_port(context):
print("Port Disconnecting")
ser.close()
def register():
register_class(TEST_OT_test_op)
register_class(TEST_PT_panel)
bpy.utils.register_class(ModalTimerOperator)
def unregister():
unregister_class(TEST_OT_test_op)
unregister_class(TEST_PT_panel)
bpy.utils.unregister_class(ModalTimerOperator)
if __name__ == '__main__':
register()
*Here is code for arduino mega
#include <Servo.h> // Header for Servo operation
Servo myservo; // Define Object
//=========================================================================================================
//Motor Pins
int smDirectionPin1 = 55; //pin number for stepper motor 1 direction
int smStepPin1 = 54; //pin number for motor 1 steps
int smDirectionPin2 = 61; //pin number for stepper motor 2 direction
int smStepPin2 = 60; //pin number for motor 2 steps
int smEnable1 = 38; //stepper driver enable pin
int smEnable2 = 56; //stepper driver enable pin
//---------------------------------------------------------------------------------------------------------
float rotationcoeff = 2.5; // number of rotation of wheel to rotate car to 360 angle
float MotorStepPerRev = 800; //number of step to rotate wheel to 360 angle
long num1, num2, num3, num4 = 0; // variable needed
String r1_data, r2_data, r3_data; // receive data storing variable
//----------------------------------------------------------------------------------------------------------
void wheels(int stp, int spd, int wd1, int wd2)
{
digitalWrite(smDirectionPin1, wd1);
digitalWrite(smDirectionPin2, wd2);
int x = 0;
for ( x = stp; x > 0; x--)
{
digitalWrite(smStepPin1, HIGH);
digitalWrite(smStepPin2, HIGH);
delayMicroseconds(spd);
digitalWrite(smStepPin1, LOW);
digitalWrite(smStepPin2, LOW);
delayMicroseconds(spd);
}
}
void stp(float x)
{
num2 = long(x);
while (num1 < num2) {
wheels(1, 1000, 1, 1);
num1++;
}
while (num1 > num2) {
wheels(1, 1000, 0, 0);
num1--;
}
num1 = long(x);
}
void rev(float y)
{
num4 = long(y);
if (num3 < num4) {
wheels(int(((MotorStepPerRev * rotationcoeff) / 360)*y), 1000, 1, 0);
//num3++;
}
else if (num3 > num4) {
wheels(int(((MotorStepPerRev * rotationcoeff) / 360)*y), 1000, 0, 1);
//num3--;
}
num3 = long(y);
}
void zaxis(int z) {
if ( z < 0)
{
myservo.write(0);
}
else if (z > 180)
{
myservo.write(180);
}
else
{
myservo.write(z);
}
}
void setup() {
myservo.attach(6);
pinMode(smDirectionPin1, OUTPUT);
pinMode(smStepPin1, OUTPUT);
pinMode(smDirectionPin2, OUTPUT);
pinMode(smStepPin2, OUTPUT);
pinMode(smEnable1, OUTPUT);
pinMode(smEnable2, OUTPUT);
digitalWrite(smEnable1, LOW);
digitalWrite(smEnable2, LOW);
digitalWrite(smDirectionPin1, HIGH);
digitalWrite(smDirectionPin2, HIGH);
Serial.begin(9600);
}
void loop() {
if (Serial.available() > 0)
{
r1_data = Serial.readString();
if ( r1_data.toFloat() == 123.321)
{
Serial.println("start");
while (!Serial.available());
r1_data = Serial.readString();
Serial.println("dones");
while (!Serial.available());
r2_data = Serial.readString();
Serial.println("doner");
while (!Serial.available());
r3_data = Serial.readString();
Serial.println("donez");
zaxis(r3_data.toInt());
stp(r1_data.toFloat());
rev(r2_data.toFloat());
Serial.println("done");
}
}
}
Here is video for final test run
Focus on car
This clip is 10x to 6x faster respectively since whole was slow very slow. and you see I wanted to write R but there is issue in angle it turn but It wrote R as you see.
To confirm issue and to see where exact error is in blender script or firmware I tested firmware code independently
*Here is test code
#include <Servo.h> // Header for Servo operation
Servo myservo; // Define Object
//=========================================================================================================
//Motor Pins
int smDirectionPin1 = 55; //pin number for stepper motor 1 direction
int smStepPin1 = 54; //pin number for motor 1 steps
int smDirectionPin2 = 61; //pin number for stepper motor 2 direction
int smStepPin2 = 60; //pin number for motor 2 steps
int smEnable1 = 38; //stepper driver enable pin
int smEnable2 = 56; //stepper driver enable pin
//---------------------------------------------------------------------------------------------------------
float rotationcoeff = 2.8; // number of rotation of wheel to rotate car to 360 angle
int MotorStepPerRev = 799; //number of step to rotate wheel to 360 angle
long num1, num2, num3, num4 = 0; // variable needed
String r1_data, r2_data, r3_data; // receive data storing variable
//----------------------------------------------------------------------------------------------------------
void wheels(int stp, int spd, int wd1, int wd2)
{
digitalWrite(smDirectionPin1, wd1);
digitalWrite(smDirectionPin2, wd2);
int x = 0;
for ( x = stp; x > 0; x--)
{
digitalWrite(smStepPin1, HIGH);
digitalWrite(smStepPin2, HIGH);
delayMicroseconds(spd);
digitalWrite(smStepPin1, LOW);
digitalWrite(smStepPin2, LOW);
delayMicroseconds(spd);
}
}
void stp(float x)
{
num2 = long(x);
while (num1 < num2) {
wheels(1, 1000, 1, 1);
num1++;
}
while (num1 > num2) {
wheels(1, 1000, 0, 0);
num1--;
}
num1 = long(x);
}
void rev(float y)
{
num4 = long(y);
while (num3 < num4) {
wheels(int((MotorStepPerRev * rotationcoeff) / 360), 1000, 1, 0);
num3++;
}
while (num3 > num4) {
wheels(int((MotorStepPerRev * rotationcoeff) / 360), 1000, 0, 1);
num3--;
}
num3 = long(y);
}
void zaxis(int z) {
if ( z < 0)
{
myservo.write(0);
}
else if (z > 180)
{
myservo.write(180);
}
else
{
myservo.write(z);
}
}
void setup() {
myservo.attach(6);
pinMode(smDirectionPin1, OUTPUT);
pinMode(smStepPin1, OUTPUT);
pinMode(smDirectionPin2, OUTPUT);
pinMode(smStepPin2, OUTPUT);
pinMode(smEnable1, OUTPUT);
pinMode(smEnable2, OUTPUT);
digitalWrite(smEnable1, LOW);
digitalWrite(smEnable2, LOW);
digitalWrite(smDirectionPin1, HIGH);
digitalWrite(smDirectionPin2, HIGH);
Serial.begin(9600);
}
void loop() {
zaxis(0);
stp(1000);
rev(90);
stp(2000);
rev(180);
stp(3000);
rev(270);
stp(4000);
rev(360);
delay(10000);
}
Here the result
This code is independently running mean I pre code it to draw square. But as you can see there is shift in angle each time it turn else covering distance all are equal. This conclude there is some error in written code that needed fixing. since two make sure error is not due to wheel slip I done one more test
Here I pause one wheel and kept rotating another one to see How perfect it draw circle. This I have done just to test movement perfection
Click To visit group machine week page and to Known more about our project
Learning Outcomes:
For this week I am done. As you see there are issue with code It is not perfect So I will work with it personally in future and continue this project in a different form. To park group project here I needed to stop. Apart from writing firmware and interface most of my time and energy consume in troubleshooting design because I have expertise in Electronic and computing. Supporting other in completing their task and with that working on my own task was chanllenging but I cant ignore this things in my group because goal was to complete project not just to do my job only. So with all that struggle I managed this much documentation and I learn blender script from this process and I am happy about it.