sherzaad:
not here to judge. Just want to see how you put your words in code. that's the beauty of code, human language may vary but code remains the same.
I actually would be gladly judged and corrected.
This is the code I have now. Unfinished and mostly untested.
Is part of a machine that I designed and 90% build. The purpose of this machine is to bend wire in 3 dimension.
youtube video of concept machine
I was actually thinking about opensource the machine mechanic project (mostly 3d printed) and code, possibly with the intention to get some help, but I wouldn't know where to start....
If interested I can post a picture from 3d cad of the machine design.
The electronics are :
3 arduino nano, one for each axis. ( this design choice might be questionable but I preferred having one controller per axis. in my mind this way I can complete each axis as an individual software project. Since I am just a beginner I look at it as a less steep step. also the machine does only need to move one axis at a time).
1 arduino mega with tft lcd and sd card (still with the postman - this will be the master device, from which to select the actual piece to be bended and eventually modify the part... still no clue on all of this. will see).
it will send to each axis the new setpoint and wait for response to proceed with next axis.
-
first axis
wire feeder. two stepper motors on same driver with 1000ppr encoder moved only by the wire. COMPLETED.
-
second axis
rotation of head around wire. one stepper and one angle sensor read via I2c. full 360 rotation allowed. no endstops.
-
third axis
actual bender. one reduced stepper and angle sensor as per previous axis. full 360 rotation allowed. no endstop. motor power and sensor reading via slipring for allowing full rotation. code to be written. possibly very similar to previous axis.
#include <Wire.h> //modified
#include <Adafruit_ADS1015.h> // modified
#include <FastPID.h>
#include <TimerOne.h>
int debug = 0; // debug
////// adafruit library is edited to set sample rate of ADS1115 to 860Hz
////// Wire library is edidited for a frequency of 400kHz
Adafruit_ADS1115 ads(0x48); // Use this for the 16-bit version
int IngressoADC = 0; // imposta canale adc sull'ADS1115
float Kp = 28, Ki = 0, Kd = 20.5, Hz = 10; // PID settings (to be modified)
int output_bits = 16;
bool output_signed = true;
FastPID myPID(Kp, Ki, Kd, Hz, output_bits, output_signed);
const int PidCorrection = 2580; // PID correction output
volatile int setpoint = 0; // where my motor has to move to
volatile bool hold = 0; // hold in position or move
volatile int sensorValue = 0; // sensor reading
int sensorMAX = -32768; // max reading of sensor value
int sensorMIN = 32767; // max reading of sensor value
int diff_error = 30; // max accattable error for hold or positioning. (to be modified)
bool check = 0; // just a check
bool direzione = 0; // direction of stepper
/////////// motor pin definition
const byte ENA = 7; // enable pin
const byte DIR = 8; // direction pin
const byte STEPpin = 9; // pulses pin
/////////// duty cycle and motor frequency
int DUTY = 300;
int PWM = 80; //(lower number higher frequency)
/////////// I2c address definition
int I2cAddress = 3;
void setup(void)
{
/////////// debug check
pinMode(13, OUTPUT);
Serial.begin(250000);
//Wait for two seconds or till data is available on serial,
//whichever occurs first.
while (Serial.available() == 0 && millis()<2000);
if (Serial.available()>0){
//If data is available, enter here.
int test = Serial.read(); // Clear the input buffer
Serial.println("DEBUG"); // Give feedback indicating mode
debug = 1; // Enable debug
digitalWrite(13, HIGH);
}
else{ // disable debug
Serial.end();
digitalWrite(13, LOW);
}
/////////// setup I2c
Wire.begin(I2cAddress); // join i2c bus with address #2
Wire.onReceive(receiveEvent); // register event function
//////////////// setup pid
myPID.setOutputRange(80, 2500);
///////////// setup stepper output
pinMode(DIR, OUTPUT); //direction
pinMode(ENA, OUTPUT); //enable (active low)
digitalWrite(ENA, HIGH); //motor off
digitalWrite(DIR, HIGH); //set direction
Timer1.initialize();
Timer1.pwm(STEPpin, DUTY, PWM); //initialize stepper pulses (to be removed)
Timer1.stop(); //stop stepper pulses
//////////// debug
if (debug == 1) {
if (myPID.err()) {
Serial.println("There is a configuration error!");
for (;;) {}
}
Serial.println("Getting single-ended readings from AIN0");
Serial.println("ADC Range: 2/3x gain +/- 6.144V 1 bit = 0.1875mV");
}
/////////// setup ADS1115
ads.setGain(GAIN_TWOTHIRDS); // set adc to 2/3
ads.begin();
/////////// find min ad max sensor values rotating at low speed
digitalWrite(ENA, LOW);
Timer1.pwm(STEPpin, DUTY, 4500);
for (int i = 0; i < 32300; i++){
CalibrazioneSensore();
}
digitalWrite(ENA, HIGH); //motor off
//////////// debug
if (debug == 1) {
Serial.println("valore massimo sensore");
Serial.println(sensorMAX);
Serial.println("valore minimo sensore");
Serial.println(sensorMIN);
}
}
void loop(void)
{
///////// find PWM output for stepper using PID
uint16_t output = myPID.step(setpoint, sensorValue);
PWM = (PidCorrection + (-output));
CalibrazioneSensore();
if (hold == 0) {
digitalWrite(DIR, direzione);
Timer1.pwm(STEPpin, DUTY, PWM);
//////////// debug
if (debug == 1) {
Serial.println(PWM);
Serial.println(sensorValue);
}
}
/////////////// to be rewritten
/////////////// what should I do if motor has reached target
if (hold == 0 && sensorValue <= setpoint + diff_error && check == 0) {
Timer1.stop();
hold = 1;
I2cSendOK();
check = 1;
}
if (hold == 1) {
holdPosition();
}
//////////// debug
if (debug == 1) {
Serial.println(ads.readADC_SingleEnded(IngressoADC));
}
}
//// receive new setpoint
void receiveEvent(int rcve) {
////// receive new setpoint via I2c
check = 0;
int iRXVal;
if (Wire.available() >= 2) // Make sure there are two bytes.
{
for (int i = 0; i < 2; i++) // Receive and rebuild the integer
iRXVal += Wire.read() << (i * 8);
}
int x = iRXVal; // receive byte as an integer
//////////// debug
if (debug == 1) {
Serial.println("ricevo via I2c");
Serial.println(iRXVal); // Print the result.
Serial.println(x); // print the integer
}
if (x > -32768) {
/////////////// what to do if I received a new value via I2c
// set direction of rotation
if (x > 0) {
direzione = 1;
hold = 0;
setpoint = map(x, 0, 3600, sensorMIN, sensorMAX); // map angle values in sensor values (should be viceversa??)
}
if (x < 0) {
direzione = 0;
hold = 0;
setpoint = map(x, 0, 3600, sensorMIN, sensorMAX); // map angle values in sensor values (should be viceversa??)
}
if (x == 0) {
direzione = 0;
hold = 1;
}
digitalWrite(ENA, LOW); //enable motor
}
else
{
////////////// if I receive this -32768 via I2c
digitalWrite(ENA, HIGH); //disattiva motore
}
}
//// send setpoint reached - movement completed
void I2cSendOK() {
////// send -555 / setpoint reached
int x = -555;
Wire.beginTransmission(1); // transmit to device #1 (master)
Wire.write((byte*)& x, 2); // Transmit the 'int', one byte at a time.
Wire.endTransmission(); // stop transmitting
//////////// debug
if (debug == 1) {
Serial.println("inviato ok (-555)");
}
}
//// hold position like a servo
void holdPosition() {
sensorValue = ads.readADC_SingleEnded(IngressoADC);
if (sensorValue <= setpoint && abs(sensorValue - setpoint) > diff_error) { // to be modified
//todo: set direction of rotation and functions for math around the 0 point
//XXXXXXXXXXXXX
//run motor
digitalWrite(DIR, direzione);
Timer1.pwm(STEPpin, DUTY, PWM);
CalibrazioneSensore(); // keep veryfy if sensor has new range of values
}
Timer1.stop(); // stop pulses to motor
}
//// calibrate minimum and maximum sensor values
void CalibrazioneSensore () {
sensorValue = ads.readADC_SingleEnded(IngressoADC);
if (sensorValue > sensorMAX) {
sensorMAX = sensorValue;
}
if (sensorValue < sensorMIN) {
sensorMIN = sensorValue;
}
}