Declaring digital signal

I am working with a 3D printer that has a Gen 6 board having atmega644A. The main program on that controller can be accessed from here:

http://forums.reprap.org/read.php?13,92469

I have connected the I2C port of the Gen 6 board (Generation 6 Electronics - RepRap) with pin 4 and 5 of the Arduino Uno. The connections are fine and this is the code that I am currently running on the Arduino

#include <Wire.h>

//i2c address of the gen 6
int REP_RAP_ADDR = 4;
//my address
int CP_ADDR = 5;

void receiveEvent(int howMany)
{
  while(0 < Wire.available()) // loop through all
  {
    char c = Wire.receive(); // receive byte as a character
    Serial.print(c);         // print the character       
  }
}

void sendGCode(char* GCode)
{
  Wire.beginTransmission(REP_RAP_ADDR);
  Wire.send(GCode);
  Wire.endTransmission();   
}

void setup()
{
  Wire.begin(CP_ADDR);
  Wire.onReceive(receiveEvent); // register event so that anything received on i2c is sent to the serial

  //Test gcode, this should send the machine's X, Y and Z to home
  sendGCode("G28 X0 Y0 Z0\n");
}

void loop()
{
  
}

This program is sending the three axes to home position via I2C. Now I need a digital signal from say pin 2 of the Arduino. I got it with a simple code:

int ledPin = 2;                 // LED connected to digital pin 2

void setup()
{
  pinMode(ledPin, OUTPUT);      // sets the digital pin as output
}

void loop()
{
  digitalWrite(ledPin, HIGH);   // sets the LED on
  delay(1000);                  // waits for a second
  digitalWrite(ledPin, LOW);    // sets the LED off
  delay(1000);                  // waits for a second
}

LED is working fine but I want the main program in the Gen 6 to know that there is a digital signal at pin 2 of Arduino. So when the printer prints, the digital signal is 5V (LED is ON) and when the printer is not printing, it should be 0.

I combined these two codes and tried some routines but I am not getting the desired result :frowning:
Any suggestions.....

Something like:

volatile long last_received_time;

void receiveEvent(int howMany)
{
  while(0 < Wire.available()) // loop through all
  {
    char c = Wire.receive(); // receive byte as a character
    last_received_time = millis ();  // remember when we last got something
  }
}

void loop()
{

  // light LED if we received data in the last second

   if (millis () - last_received_time > 1000)  // if something in the last second
     digitalWrite(ledPin, HIGH);
   else
     digitalWrite(ledPin, LOW);

  // any other stuff
}

Or more simply, but slightly more obscure:

// light LED if we received data in the last second
    digitalWrite(ledPin, millis () - last_received_time > 1000);

I combined these two codes and tried some routines but I am not getting the desired result
Any suggestions.....

It would be much more useful, I think you'll agree, if you told us what results you desired, and what results you do get.

Desired Result: LED "ON" when the printer is printing and "OFF" when it is not.

My Results: LED blinking and not exactly following the pattern described above :~

I combined these two codes

And didn't show us how...

This is what I was doing

#include <Wire.h>
#define LED_OUT 2


//i2c address of the gen 6
int REP_RAP_ADDR = 4;
//my address
int CP_ADDR = 5;
int x;

void receiveEvent(int howMany)
{
x = Wire.receive();    
  while(0 < Wire.available()) // loop through all
  {
    char c = Wire.receive(); // receive byte as a character
    Serial.print(c);         // print the character       
  }
}

void sendGCode(char* GCode)
{
  Wire.beginTransmission(REP_RAP_ADDR);
  Wire.send(GCode);
  Wire.endTransmission();   
}

void setup()
{
  Wire.begin(CP_ADDR);
  Wire.onReceive(receiveEvent); // register event so that anything received on i2c is sent to the serial

  //Test gcode, this should send the machine's X, Y and Z to home
  sendGCode("G28 X0 Y0 Z0\n");
Wire.begin(4);                // join i2c bus with address #4
  Wire.onReceive(receiveEvent); // register event
  Serial.begin(9600);           // start serial for output
  pinMode(LED_OUT, OUTPUT);
  digitalWrite(LED_OUT, LOW);
  x = 0;

}

void loop()
{
 if (x > 0) {
    for (int i=0; i<x; i++) {
      digitalWrite(LED_OUT, HIGH);
      delay(200);
      digitalWrite(LED_OUT, LOW);
      delay(200);
    }
    x = 0;
    delay(1000);
  }
  delay(100);
 
}

I know I should not be using delays but some command that can read printing and non-printing states. But I am working on that :slight_smile:

I am getting continuous 3.7V using the above code whether it is printing or not printing and the LED id "ON"

I tried Nick's code that he mentioned above

#include <Wire.h>
int ledPin = 2;   
             
volatile long last_received_time;
//i2c address of the gen 6
int REP_RAP_ADDR = 4;
//my address
int CP_ADDR = 5;

void receiveEvent(int howMany)
{  

  while(0 < Wire.available()) // loop through all
  {
    char c = Wire.receive(); // receive byte as a character
Serial.print(c);        
    last_received_time = millis ();  // remember when we last got something
  }
}

void setup()
{
  pinMode(ledPin, OUTPUT);      // sets the digital pin as output
Wire.begin(CP_ADDR);
  Wire.onReceive(receiveEvent); // register event so that anything received on i2c is sent to the serial
}

void loop()
{

  // light LED if we received data in the last second

   if (millis () - last_received_time > 1000)  // if something in the last second
     digitalWrite(ledPin, HIGH);
   else
     digitalWrite(ledPin, LOW);

  // any other stuff
}

I am getting round about 8.8V continuous whether I am printing or not and the LED is "OFF" :~

I am getting round about 8.8V continuous whether I am printing or not and the LED is "OFF"

You are reading 8.8 volts on a 5 volt board? I think it's time to get a new meter. Or, to learn to read the one that you have.

What are you measuring, anyway?

It really isn't clear WHEN you want the pin on. Try to define it in terms of the receiveEvent code. It seems to me like that is when the pin's state is to be set.

Oops I was going for 4.8, my bad :stuck_out_tongue:

I am measuring voltage at pin 2 which I have set as output and I want it to be 5V (LED ON)when I am printing something and 0 (LED OFF)when I am not printing.

I am trying to define it in the Receive Code but no luck. That is the reason I asked the question on the forum my friend :stuck_out_tongue:

Can you forget the Wire stuff, and just write a simple Blink sketch for the LED, and report back what happens?

As I mentioned in the opening post, this is the blink code and it works fine my friend :slight_smile:

int ledPin = 2;                 // LED connected to digital pin 2

void setup()
{
  pinMode(ledPin, OUTPUT);      // sets the digital pin as output
}

void loop()
{
  digitalWrite(ledPin, HIGH);   // sets the LED on
  delay(1000);                  // waits for a second
  digitalWrite(ledPin, LOW);    // sets the LED off
  delay(1000);                  // waits for a second
}

I am measuring voltage at pin 2 which I have set as output and I want it to be 5V (LED ON)when I am printing something and 0 (LED OFF)when I am not printing.

As in where the comments are?

void receiveEvent(int howMany)
{  
  while(0 < Wire.available()) // loop through all
  {
    // Turn the LED on
    char c = Wire.receive(); // receive byte as a character
    Serial.print(c);        
    last_received_time = millis ();  // remember when we last got something
  }
  // Turn the LED off
}

This test code works for me, it flashes the LED for a second whenever it receives I2C data. This is the master (simulating the reprap sending data):

#include <Wire.h>

#define SLAVE_ADDRESS 5
 
void setup ()
{
  Wire.begin();   
}  // end of setup

void loop()
{
  Wire.beginTransmission (SLAVE_ADDRESS);
  Wire.send ("hello, world");
  Wire.endTransmission ();
    
  delay (4000);   
}  // end of loop

And this is the slave (receiving the data):

#include <Wire.h>
int ledPin = 13;   

volatile long last_received_time;

//my address
int CP_ADDR = 5;

void receiveEvent(int howMany)
{  

  while(0 < Wire.available()) // loop through all
  {
    char c = Wire.receive(); // receive byte as a character
    last_received_time = millis ();  // remember when we last got something
  }
}

void setup()
{
  pinMode(ledPin, OUTPUT);      // sets the digital pin as output
  Wire.begin(CP_ADDR);
  Wire.onReceive(receiveEvent); // register event so that anything received on i2c is sent to the serial
}

void loop()
{

  // light LED if we received data in the last second

  if (millis () - last_received_time < 1000)  // if something in the last second
    digitalWrite(ledPin, HIGH);
  else
    digitalWrite(ledPin, LOW);

  // any other stuff
}

I admit I had the test backwards. In my earlier post I had:

  if (millis () - last_received_time > 1000)  // if something in the last second

But it should have read:

  if (millis () - last_received_time < 1000)  // if something in the last second

You need to make sure the the CP_ADDR is the address of the slave, and this needs to be the address that the reprap is sending to. You don't need to know the reprap address in the slave. It just responds to anything addressed to it, wherever that comes from.

You are absolutely right my friend. When I upload the code for Master in Gen 6 and for Slave in Arduino, the LED does blink.

But I want the LED to be blinking based on printing and non-printing states, like this

1(ON) Printing
0(OFF) Not printing

I guess I am confused and I am confusing everyone as well. Let's start from the top :slight_smile:
Here is the code for the Gen 6 program

http://forums.reprap.org/read.php?13,92469

In this code, I have initialized I2C at line 353-361

void receiveEvent(int howMany)
{

}

void requestEvent()
{
  Wire.send("start");
}

Then at line 396-401

Serial.begin(HOST_BAUD);
  Serial.println("start");
  
  Wire.begin(4);
  Wire.onReceive(receiveEvent); // register event
  Wire.onRequest(requestEvent); // register event

At line 456-460

#define I2CMODE 1
#define SERIALMODE 0

int inputMode = SERIALMODE;

This is for Gen 6.
Arduino has the following program at the moment

#include <Wire.h>

//i2c address of the gen 6
int REP_RAP_ADDR = 4;
//my address
int CP_ADDR = 5;

void receiveEvent(int howMany)
{
  while(0 < Wire.available()) // loop through all
  {
    char c = Wire.receive(); // receive byte as a character
    Serial.print(c);         // print the character       
  }
}

void sendGCode(char* GCode)
{
  Wire.beginTransmission(REP_RAP_ADDR);
  Wire.send(GCode);
  Wire.endTransmission();   
}

void setup()
{
  Wire.begin(CP_ADDR);
  Wire.onReceive(receiveEvent); // register event so that anything received on i2c is sent to the serial

  //Test gcode, this should send the machine's X, Y and Z to home
  sendGCode("G28 X0 Y0 Z0\n");
}

void loop()
{
  
}

Now I need a digital signal at Arduino (say pin 2) that will just be 1 when printer is printing and 0 when it is not.
How to tell Gen 6 that there is a digital signal at pin 2 of Arduino and when Gen 6 is printing, it should turn the signal to be 1 (if using LED then ON) and 0 when not printing.

You've completely lost me. Is Gen 6 the reprap? Can we use consistent names?

How to tell Gen 6 that there is a digital signal at pin 2 of Arduino and when Gen 6 is printing, it should turn the signal to be 1 (if using LED then ON) and 0 when not printing.

You want to tell Gen 6 that Gen 6 is printing? Doesn't it know if it itself is printing without all this stuff?

Is Gen 6 the reprap? Can we use consistent names?

Yes, Gen 6 is Reprap. From now on, we will use RepRap and Arduino. These are the two names :slight_smile:

And RepRap is printing, it knows that. But the pin on Arduino doesn't know that. The LED attached to pin does not respond to printing :~

Let me elaborate things a bit here.
I want to use a different device to print and it is other than the one connected to the reprap. In order to control that device, I need one digital and 1 analogue signal. Here is the code that I am using:

#include <Wire.h>
#include "SPI.h" // necessary library

int del=2; // used for various delays
word outputValue = 0; // a word is a 16-bit number
byte data = 0; // and a byte is an 8-bit number
int ledPin = 4;                 // LED connected to digital pin 4
int B = ledPin;

//i2c address of the gen 6
int REP_RAP_ADDR = 4;
//my address
int CP_ADDR = 5;

void receiveEvent(int howMany)
{
  while(0 < Wire.available()) // loop through all
  {
    char c = Wire.receive(); // receive byte as a character
    Serial.print(c);         // print the character       
  }
}

void sendGCode(char* GCode)
{
  Wire.beginTransmission(REP_RAP_ADDR);
  Wire.send(GCode);
  Wire.endTransmission();   
}

void requestEvent()
{
  Wire.beginTransmission(CP_ADDR);  
  Wire.send("javaid");
  Wire.endTransmission(); 
}
void setup()
{
    
  Wire.begin(CP_ADDR);
  Wire.onReceive(receiveEvent); // register event so that anything received on i2c is sent to the serial

  //Test gcode, this should send the machine's X, Y and Z to home
  sendGCode("G28 X0 Y0 Z0\n");
  pinMode(B, OUTPUT);      // sets the digital pin as output
  //set pin(s) to input and output
  pinMode(10, OUTPUT);
  SPI.begin(); // wake up the SPI bus.
  SPI.setBitOrder(MSBFIRST);

}

void loop()
{
  {
  while (digitalRead(B)){    //read LED
  if (B == 1)                 // if the value is 1
  digitalWrite(B, HIGH);   // sets the LED on
  else                 
  digitalWrite(B, LOW);    // sets the LED off
                 
}
  }
  int A;
 for (int A=0; A<=4095; A++)
  {
    outputValue = A;
    digitalWrite(10, LOW);
    data = highByte(outputValue);
    data = 0b00001111 & data;
    data = 0b00110000 | data;
    SPI.transfer(data);
    data = lowByte(outputValue);
    SPI.transfer(data);
    digitalWrite(10, HIGH);
    delay(del);
  }
  delay(del+25);
  for (int A=4095; A>=0; --A)
  {
    outputValue = A;
    digitalWrite(10, LOW);
    data = highByte(outputValue);
    data = 0b00001111 & data;
    data = 0b00110000 | data;
    SPI.transfer(data);
    data = lowByte(outputValue);
    SPI.transfer(data);
    digitalWrite(10, HIGH);
    delay(del);
  }
  delay(del+25);
}

This goes in the Arduino.
It might look a bit messy because it is a combination of 3 codes (I2C+SPI+LED)
I used SPI protocol to get an analogue signal from Arduino using MCP4921 chip. Nick helped me out with the initialization in the reprap main program. I tried declaring Analogue signal as "A" and Digital signal as "B." If I made a mistake in doing so, kindly let me know.
I am declaring A and B because I will be using them in the reprap main program.

Here is the code and in the process_g_code file, I have tried to initialize A and B (Line 41,42,79,80,386,387). I am not sure whether what I have initialized is correct or not.

http://forums.reprap.org/read.php?13,94154

And in the Arduino code, I have tried to initialize A and B as well.
And when I try printing by giving certain values to A and B, the LEDs don't respond accordingly (OFF when 0 and ON when 1).
There might be a lot wrong with what I am doing and that is exactly the reason why I am asking for help. Hope to see some positive answers :slight_smile:

int del=2.5;

?

if (B = 1)

Intentional?

In fact,

if (B = 1)                 // if the value is 1
  digitalWrite(B, HIGH);   // sets the LED on
  else                 
  digitalWrite(B, LOW);

looks very suspicious - this will always write HIGH to pin 1.

Remember, just because it compiles doesn't mean it will work.

int del=2;

This delay is for the SPI routine. This allows the LED to fade away slowly enough.

if (B == 1)

Yes, it is intentional. Whenever I send 1, I want the LED to light up.
And I know just because something compiled, doesn't mean that it is right. But that is what I am trying to figure out. What is wrong with it and how can I make it right :~

This delay is for the SPI routine.

But, an int only holds whole numbers. 2.5 will be truncated to 2. So, why bother with the .5 on the end?

Yes, it is intentional.

You are intentionally assigning the value of 1 to B? That statement is NOT performing an equality test. That would require ==, not =.