Hi folks,
Background:
I have an I2C master Uno sending a long type to an I2C slave Uno which controls a stepper motor with virtually uninterrupted pulses, leaving the master to do other more complex processing. I'm using the I2C_Anything library for this http://www.gammon.com.au/forum/?id=10896. It's handy, but not entirely necessary.
The Problem:
I'd like to send an initial value to the slave after the master reboots the slave, as shown in my code in setup(). The slave does not register the initial communication and stays at it's initialized value of "1000." As soon as a command is send to the slave from loop() the slave reads it. Why the heck won't it read when sent from setup()? I've messed with delays to allow the slave time to recover after reboot, but no size of value effects the above stated problem.
I2C MASTER:
//This is a program for the I2C Master which does all the processing and sends it to the
//I2C Slave which controls a stepper motor without much processing time.
//The Master program will be expanded after communication issues are straighened out.
//It is assumed that all timing values in this program are in microseconds unless otherwise noted
#include <I2C_Anything.h>
#include <Wire.h>
int SLAVE_ADDRESS = 1;
int slave_reset_pin = 12;
long max_delay = 9830; //this is the biggest amount of time delay sent to the slave arduino
long min_delay = 12; //this is the smallest amount of time delay sent to the slave arduino
long received_delay = 10000; //converted value received from serial terminal
char received_char[16]; //characters received from serial terminal
void setup(){
pinMode(slave_reset_pin, OUTPUT);
pinMode(13, OUTPUT);
digitalWrite(13, LOW);
Wire.begin();
Serial.begin(115200);
delay(100);
//reset the slave arduino!!!!!!!!!!!!!!!
digitalWrite(slave_reset_pin, LOW);
delay(100);
digitalWrite(slave_reset_pin, HIGH);
delay(200);
//THIS WON'T DO ANYTHING!!!!!!!!!!!!!! WHY????????????????????
Wire.beginTransmission(SLAVE_ADDRESS);
I2C_writeAnything(0); //if slave receives a 0 is stops the stepper motor
Wire.endTransmission();
}
void loop(){
//Serial com with computer can receive up to 16 characters (more than enough)
//I like this kind of serial communication. It's exciting because I figured it
//out on my own for the first time, without referencing THE INTERNET :)
if(Serial.available() > 0){
for(int i = 0; i < 16; i++){
received_char[i] = Serial.read();
if(received_char[i] <= 0) //fill the remainder of the array with ascii "NULL" value
received_char[i] = 0;
}
//Convert char array to number
received_delay = atof(received_char);
//Make sure delay is within limits of the I2C slave system
if(received_delay > max_delay){
received_delay = 0; //send 0 to slave so it stops the stepper
}else{
if(received_delay < min_delay)
received_delay = min_delay;
}
//Send data to slave system
Wire.beginTransmission(SLAVE_ADDRESS);
I2C_writeAnything(received_delay);
Wire.endTransmission();
}
//print feedback for user on computer - for debugging
Serial.print(received_delay); Serial.print("\t\t");
for(int i = 0; i < 16; i++)
Serial.print(received_char[i]);
Serial.println("");
delay(500);
}
I2C SLAVE:
#include <I2C_Anything.h>
#include <Wire.h>
int MY_ADDRESS = 1; //I2C Slave address
int Direction_Pin = 2;
int Step_Pin = 3;
int MS1_Pin = 4;
int MS2_Pin = 5;
int ms1 = 0;
int ms2 = 0;
long received_delay = 1000; //initialize with some foo foo values
double step_delay = 300;
void setup(){
Wire.begin(MY_ADDRESS);
Wire.onReceive(receiveEvent);
pinMode(Direction_Pin, OUTPUT);
pinMode(Step_Pin, OUTPUT);
pinMode(MS1_Pin, OUTPUT);
pinMode(MS2_Pin, OUTPUT);
digitalWrite(Direction_Pin, LOW);
digitalWrite(MS1_Pin, LOW);
digitalWrite(MS2_Pin, LOW);
delay(100);
}
void loop()
{
step_delay = step_calc(received_delay);
micro_Stepping();
if(step_delay != 0){
digitalWrite(Step_Pin, LOW); // This LOW to HIGH change is what creates the
digitalWrite(Step_Pin, HIGH); // "Rising Edge" so the easydriver knows to when to step.
delayMicroseconds(step_delay);
}
}
//get the new delay time if data is send from the I2C master
void receiveEvent(int howMany)
{
if (howMany >= (sizeof received_delay)){
I2C_readAnything(received_delay);
}
}
//step_calc() and mircro_Stepping() calculate and assign
//the values of the micro-Stepping pins on the stepper driver
double step_calc(long delay_input){
if(delay_input < 0){
ms1 = 0;
ms2 = 0;
return 0;
}
if(delay_input >= 0 && delay_input < 170){
ms1 = 0;
ms2 = 0;
return delay_input * 10;
}
if(delay_input >= 170 && delay_input < 400){
ms1 = 1;
ms2 = 0;
return delay_input * 5;
}
if(delay_input >= 400 && delay_input < 1000){
ms1 = 0;
ms2 = 1;
return delay_input * 10;
}
if(delay_input >= 1000){
ms1 = 1;
ms2 = 1;
return delay_input * 5;
}
}
void micro_Stepping(){
if(ms1 == 1){
digitalWrite(MS1_Pin, HIGH);
}else{
digitalWrite(MS1_Pin, LOW);
}
if(ms2 == 1){
digitalWrite(MS2_Pin, HIGH);
}else{
digitalWrite(MS2_Pin, LOW);
}
}
I'm sure there are better ways to write this code. I'll clean it up later, but for now I want the functionality to work.
Any thoughts?