Continue to Site

Welcome to EDAboard.com

Welcome to our site! EDAboard.com is an international Electronics Discussion Forum focused on EDA software, circuits, schematics, books, theory, papers, asic, pld, 8051, DSP, Network, RF, Analog Design, PCB, Service Manuals... and a whole lot more! To participate you need to register. Registration is free. Click here to register now.

Declaring Digital Signal

Status
Not open for further replies.

Javaid1

Newbie level 6
Joined
Jul 17, 2011
Messages
13
Helped
0
Reputation
0
Reaction score
0
Trophy points
1,281
Activity points
1,395
Hi All,

I am working on a 3D printer with Generation 6 electronics board having atmega644a. The main code for Gen 6 is here:
Five D Code
If you have a look at the code, you can see that I have initialized I2C at line 353-361
Code:
void receiveEvent(int howMany) 
{ 

} 

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

Then at line 396-401
Code:
Serial.begin(HOST_BAUD); 
  Serial.println("start"); 
  
  Wire.begin(4); 
  Wire.onReceive(receiveEvent); // register event 
  Wire.onRequest(requestEvent); // register event
At line 456-459
Code:
#define I2CMODE 1 
#define SERIALMODE 0 

int inputMode = SERIALMODE;

All of this is already in the Gen 6 code.
Then I connected Arduino Uno (having atmega328)with the Gen 6 board and started communicating via I2C.

Code:
#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 from Arduino (say pin 2). I have connected a LED at pin 2. I want Gen 6 to know that there is a digital signal at pin 2 of Arduino and when Gen 6 is printing, the digital signal should be 1 and when it is not printing, it should be 0.
How to achieve this ??
 

Have you considered coding an Interrupt Service Routine (ISR) to monitor changes on that pin? This would be the most timely response, but you could always poll for changes.
 
Are you suggesting something like this ?

int ledPin = 2; // LED connected to digital pin 2
volatile long last_received_time;
void setup()
{
pinMode(ledPin, OUTPUT); // sets the digital pin as output
Serial.begin(9600);
}

void loop()
{
last_received_time = millis (); // remember when we last got something
while (digitalRead(2)){
if (millis () - last_received_time < 1000) // if something in the last second
digitalWrite(ledPin, HIGH);
else
digitalWrite(ledPin, LOW);
}
}
 

Yes, but this would be the less desirable "polling" version.

With an interrupt, your MCU wouldn't be waiting around for some event to occur. Using an ISR, an event triggers the MCU to take action and then returns to its main loop and tasks.

BigDog
 

I have never used interrupts before but here is what I have found

int pin = 13;
volatile int state = LOW;

void setup()
{
pinMode(pin, OUTPUT);
attachInterrupt(0, blink, CHANGE);
}

void loop()
{
digitalWrite(pin, state);
}

void blink()
{
state = !state;
}

Will you please explain how this is going to help solve my problem :???:
 

Ok, but first what is a Generation 6 Board? And what compiler and IDE are you using to generate code for the board?
 

Generation 6 is an electronics board
https://reprap.org/wiki/Generation_6_Electronics
It has atmega644 and I am using Arduino 0022 to compile the code.

But my guess is that I have to change something from the lines of the main program that I mentioned in the opening post. Only then, Arduino will get a signal when Gen 6 is printing and when it is not.
 

Ok.

So it is like an Arduino on steroids. I've designing systems with AVRs for years, but I just bought my first Arduinos a couple of months ago. I acquired them mainly to checkout the Arduino development platform. I have to say, the Arduino development platform, while based on an open source C compiler, is not very interrupt centric, unlike most embedded C compilers. In many ways, it attempts to hide many of the gritty details of programming an MCU.


Most MCUs offer an interrupt system which is built into the chip's design. Some offer more complex interrupt system than others.

The basic premiss is this:

The hardware of the MCU is setup so that on an occurrence of a specific event, a pin changing levels, a timer overflow, etc, the processor jumps program execution to a particular section of code which resembles a subroutine in many ways. This section/module of code is the Interrupt Service Routine or ISR.

In your example above:

Code:
[COLOR="#008000"]int pin = 13;
volatile int state = LOW;
[/COLOR]
[COLOR="#0000FF"]void setup()
{
     pinMode(pin, OUTPUT);
     attachInterrupt(0, blink, CHANGE);
}[/COLOR]

void loop()
{
    digitalWrite(pin, state);
}

[COLOR="#FF0000"]void blink()
{
    state = !state;
}[/COLOR]

The blink subroutine is in effect the ISR (marked in red). Outside of the Arduino's development platform the usual course of action would be to initialize interrupt process by setting various bits in specific registers, in Arduino this is replaced by the setup routine contain both pinMode(pin, OUTPUT) and attachInterrupt(0, blink, CHANGE) (marked in blue) along with the two statements int pin = 13 and volatile int state = LOW (marked in green).

Rather than type a lengthy detailed explanation which would require several postings, I have found a fairly good example online with sample code so that you may evaluate the interrupt routine in person.



Study the above example and post any additional question you may have. I'll do my best to answer them.

BigDog
 
  • Like
Reactions: FvM

    FvM

    Points: 2
    Helpful Answer Positive Rating
Code:
int pbIn = 0;                  // Interrupt 0 is on DIGITAL PIN 2!

int ledOut = 4;                // The output LED pin

volatile int state = LOW;      // The input state toggle

void setup()

{               

// Set up the digital pin 2 to an Interrupt and Pin 4 to an Output

pinMode(ledOut, OUTPUT);

//Attach the interrupt to the input pin and monitor for ANY Change

attachInterrupt(pbIn, stateChange, CHANGE);

}

void loop()                    

{

//Simulate a long running process or complex task

for (int i = 0; i < 100; i++)

{

// do nothing but waste some time

delay(10);

}

}

void stateChange()
{
state = !state;
digitalWrite(ledOut, state); 
}
This code goes to the Arduino. Now I will try and explain what I got out of it and you can tell me to what extent I am correct.
I will upload this code to Arduino Uno which has pin 2 as External Interrupt and output will be seen at pin 4 by connecting a LED. Before moving forward, I want to ask about pin 2. How can I tell pin 2 when the printer is printing? I mean what command should I use? I posted the whole code in the opening post because I was unable to communicate to the Arduino when the printer is printing. Correct me if I am wrong but I think that I am back to the same problem with this interrupt routine.
 

The Gen 6 is the printer controller? And what is the purpose of the Arduino? I just want to make sure I understand the task correctly.
 

Yes, Gen 6 is the printer controller and is completely embedded on the board. Therefore, there is no means of connecting a wire to it. This is why Arduino is needed, so that I can have a digital output from any of its pins (say pin 4). This digital output should give 1 when Gen 6 is printing and 0 when it is not. Meaning therefore that Gen 6 should send a signal every time it starts printing and every time it stops. I hope that gives a better idea.
 

Ok,

So the only connection between the Gen 6 and the Arduino is the I2C bus correct?

I think I have a clearer picture. Let me give it some thought and look at your Gen 6 code and then I'll post my recommendations.

The forum is acting strange at the moment, I'm receiving any notices of postings and the members online list is vacant.

BigDog
 

So the only connection between the Gen 6 and the Arduino is the I2C bus correct?

Yes, you are absolutely correct.

And yeah, I am not receiving any notifications at all from here :shock:
 

And yeah, I am not receiving any notifications at all from here :shock:

I other words you cannot establish any communication via I2C between the boards? Was the I2C bus originally implemented to alert the Arduino the Gen 6 was printing or does it have another task?

What is the specific task or tasks of the Arduino board?
 

Arduino is used
1- To establish communication between two boards (Gen 6 & Arduino)---- DONE (the code in the opening post)
According to the code, Arduino is telling the Gen 6 to bring the 3 axes to home position.

2- To have a digital output that is 1 when the Gen 6 is printing and 0 when it is not printing----asking you about it...

I2C has been established in the main code. You can see the line numbers that I have mentioned in the opening post are specifically for the I2C.

The problem is telling Gen 6 to send a signal to Arduino when it prints so that the pin would be 1 and send a signal 0 when it is not printing.
 

And yeah, I am not receiving any notifications at all from here

That was for the forum as I was not receiving any notifications from the forum. I was just referring to the forum not I2C :)

I2C is up and running in the main code as well as the Arduino code that I have posted in the opening post.
 

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:
Code:
#include <Wire.h>
#include "SPI.h" // necessary library

int del=2.5; // 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 2
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.
RepRap Code
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
 

Figure.png

Just to clarify things a little bit more, I am attaching a figure showing what am I doing. I hope it gives a better understanding of my problem.

As you can see, RepRap (3D printer or Gen 6) is connected to computer via USB and I can print anything I want using Repsnapper software. Repsnapper is a host software in the computer through which I can upload stl files or g codes and print anything. So far so good, I guess. I connected Arduino to RepRap and started communicating via I2C (I shared the code in one of my earlier posts). Now I want 1 digital and 1 analogue signal from the Arduino.

I have a dry powder dispensing device that I intend to connect to the printer. It needs 1 analogue and 1 digital signal to run as shown. Analogue signal is controlling the amplitude (1V,2V,3V,4V,5V, doesn't matter) and Digital signal is just 1 and 0. Whenever it is 1, I can print. It is better that I stop here and first get the digital and analogue signal working with the printer. I hope it makes more sense now :???:
 

I have put this code in the 3D printer
Code:
#include <Wire.h>

#define reprap 6
#define slave 5

void setup ()
 {
 Wire.begin (reprap);
 }
 
void loop()
{
  Wire.beginTransmission (slave);
  Wire.send ("G1"); 
  Wire.endTransmission();

  Wire.beginTransmission (slave);
  Wire.send ("G28");
  Wire.endTransmission();

}

And this in Arduino
Code:
#include <Wire.h>

#define slave 5
#define LED 13

void receiveEvent (int howMany)
 {
  char buf [10];
  byte i = 0;

  while (Wire.available () > 0)
    {
    char c = Wire.receive ();
    if (i < sizeof (buf) - 1)  // check for overflow
      buf [i++] = c;
    }  // end of while

   buf [i] = 0;  // terminating null
   
  if (memcmp (buf, "G1", 2) == 0)
    digitalWrite (LED, HIGH);
  else if (memcmp (buf, "G28", 3) == 0)
    digitalWrite (LED, LOW);
}  // end of receiveEvent


void setup () 
{
  Wire.begin (slave);
  Wire.onReceive (receiveEvent);
  pinMode (LED, OUTPUT);
}  // end of setup

void loop() 
{
// nothing in main loop
}

This is the code that compares any string starting with G1 or G28 with the incoming data.
But the problem is that the LED remains ON and when I send G1 or G28, it turns OFF. It does flicker very quickly on execution of each command but still not turning ON when it receives G1 and OFF on G28. Just have a look and see if you can figure it out.
 

Status
Not open for further replies.

Part and Inventory Search

Welcome to EDABoard.com

Sponsor

Back
Top