Go Down

Topic: Declaring digital signal (Read 7853 times) previous topic - next topic

Nick Gammon


After a lot of study on arrays, this is what I have come up with.
Code: [Select]

void receiveEvent(int howMany)
{
 char incoming[4]; // don't really know what the size of a g-code would be, so work on this number :P  
...

       if(i > 4){                       //prevent data corruption in case you accidentally receive more than the array can hold
           incoming[4] = '\0';  //put a null char at the end of the array
...

Is this any good or should I start studying again  :~


Back to your studies. An array declared of length 4 like this:

Code: [Select]
char incoming[4];

... has 4 bytes:

Code: [Select]

incoming[0]
incoming[1]
incoming[2]
incoming[3]


So your write to incoming [4] will corrupt memory.
Please post technical questions on the forum, not by personal message. Thanks!

More info:
http://www.gammon.com.au/electronics

Nick Gammon

#76
Aug 28, 2011, 02:49 am Last Edit: Aug 28, 2011, 02:51 am by Nick Gammon Reason: 1

All right. Let me post the new code that I corrected with a lot of help from the posters here. This is in Reprap.
Code: [Select]

...
void loop
{
 Wire.beginTransmission (5);
 Wire.send ("G1");
 Wire.send ("G28");
}



Even if you had the Wire.endTransmission, like this:

Code: [Select]

void loop
{
 Wire.beginTransmission (5);
 Wire.send ("G1");
 Wire.send ("G28");
 Wire.endTransmission ();
}


You are now sending 5 bytes ("G1G28"). But your code you recently posted expected 4 (plus a 0x00 at the end). So when you say "don't really know what the size of a g-code would be" you know you have sent 5 bytes, right?
Please post technical questions on the forum, not by personal message. Thanks!

More info:
http://www.gammon.com.au/electronics

Nick Gammon


After a lot of study on arrays, this is what I have come up with.
Code: [Select]

void receiveEvent(int howMany)
{
  char incoming[4]; // don't really know what the size of a g-code would be, so work on this number :P 
  int length;
  while(0 < Wire.available()) // loop through all
   {
     delay(100);
    length = Wire.available();
    for (int i = 0; i < length; i++) {
        if(i > 4){                       //prevent data corruption in case you accidentally receive more than the array can hold
            incoming[4] = '\0';  //put a null char at the end of the array
            break;
        }
        incoming[i] = Wire.receive();
        }
    }
...

Is this any good or should I start studying again  :~


Let's work through what would happen if you got 5 bytes (which in fact you are sending from your test program).

You store the first 4 in "incoming" and then notice that you have more than 4 in the inner loop. But the outer loop still has Wire.available() == 1. So the outer loop keeps looping, and the inner loops keeps doing a "break". So this code will go into an infinite loop.

Why use two loops?
Please post technical questions on the forum, not by personal message. Thanks!

More info:
http://www.gammon.com.au/electronics

Javaid

To be very honest, that 4 was just a test number.

Let me make it 128. Problem solved  :)
Code: [Select]

char incoming[128];
char length;

This should do.
All right, the next issue.
Code: [Select]

void loop()
{
  Wire.beginTransmission (5);
  Wire.send ("G1");
  delay(1000);
  Wire.send ("G28");
  delay(1000);
  Wire.endTransmission();
}

Before we go any further, I am sensing that I might have done it wrong too (no surprises there  :P)
I don't want to send G1 and G28 at the same time or after a fixed interval. I want Arduino to know when G1 come (led ON) and when G28 come (led OFF), which will not happen according to what I have done here. So what should I do  :~

Nick Gammon



Code: [Select]

void loop()
{
  Wire.beginTransmission (5);
  Wire.send ("G1");
  delay(1000);
  Wire.send ("G28");
  delay(1000);
  Wire.endTransmission();
}




Did you understand what I wrote above?

Quote
The Wire library only buffers up data and does the actual sending on the Wire.endTransmission ().


In light of that, what effect do you think delay(1000) will have?
Please post technical questions on the forum, not by personal message. Thanks!

More info:
http://www.gammon.com.au/electronics

Javaid

Can I say something, I am having a feeling that I am back in school  :)
All in good humor though  :)

It should go like this
Code: [Select]

void loop()
{
  Wire.beginTransmission (5);
  Wire.send ("G1");
  Wire.endTransmission();
  Wire.send ("G28");
  Wire.endTransmission();
}

Is this correct ?

PaulS

Quote
Is this correct ?

No.

Wire.beginTransmission() and Wire.endTransmission() calls are used in pairs. One start, one end.

Javaid

#82
Aug 28, 2011, 04:04 am Last Edit: Aug 28, 2011, 05:02 pm by Javaid Reason: 1
Code: [Select]

void loop()
{
 Wire.beginTransmission (5);
 Wire.send ("G1");
 Wire.send ("G28");
 Wire.endTransmission();
}


Then I guess, like this, right !


Javaid

The LED is still OFF, like it is not receiving anything  =(

What should I do  :smiley-yell:

PaulS

Quote
What should I do

Gee, let me think for a minute.

Ooh, I know. POST YOUR CODE!!!

Javaid

#85
Aug 28, 2011, 09:10 pm Last Edit: Aug 29, 2011, 12:44 am by Javaid Reason: 1

Gee, let me think for a minute.

Ooh, I know. POST YOUR CODE!!!

Good idea. Why didn't I think of that  :P

This is in Reprap
Code: [Select]

#include <Wire.h>

//i2c address of the gen 6
int REP_RAP_ADDR = 4;
//my address
int CP_ADDR = 5;
void setup()
{  
 Wire.begin(4);
}
void loop()
{
 Wire.beginTransmission (5);
 Wire.send ("G1");
  Wire.endTransmission();
delay(1000);
Wire.beginTransmission (5);
 Wire.send ("G28");
 Wire.endTransmission();
delay(1000);
}

And this is in Arduino
Code: [Select]

#include <Wire.h>

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

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

void receiveEvent(int howMany)
{
 char incoming[128];
 while(Wire.available() < howMany); // do nothing
   for (int i = 0; i < howMany; i++) {
       if(i < 128){                      
           incoming[i] = Wire.receive();  
           incoming[i+1] = '\0';
           Serial.print(incoming);}
       }
   }
   char str1[] = "G1";
char str2[] = "G28";
 
 if (strcmp(str1, incoming) == 0){
     //turn dispenser on
     digitalWrite(2, HIGH); }
   
   if (strcmp(str2, incoming) == 0) {    
     //turn dispenser off
     digitalWrite(2, LOW);}
}
void loop()
{  
}

PaulS

Code: [Select]
        if(i > 128){                       //prevent data corruption in case you accidentally receive more than the array can hold
            incoming[128] = '\0';  //put a null char at the end of the array

So, if the array is full, write beyond the end of it. How's that working for you?

You are using strcmp () to compare what is in incoming to some fixed strings. The strcmp function is one of a family of string functions. Do you know what a string is?

I'll tell you. It's a NULL terminated array of characters. Look through your code. Where do you NULL terminate your array of characters?

If you don't NULL terminate the array, IT IS NOT A STRING (string), so you can't expect proper behavior of the strcmp function.

One of the arguments for the receiveEvent function is the number of characters to expect. They may not all have arrived by the time the function is called. Why are you not reading that number of characters?

Code: [Select]
  while(Wire.available() < howMany); // do nothing

Then, read the characters that Wire sent:
Code: [Select]
    for (int i = 0; i < howMany; i++)
    {
        if(i < 128)
        {
            incoming[i] = Wire.receive();
            incoming[i+1] = '\0';  //put a null char at the end of the array
       }
   }

Then, print what you got, and use it.

Javaid

#87
Aug 28, 2011, 09:44 pm Last Edit: Aug 28, 2011, 10:32 pm by Javaid Reason: 1
So it should go like this, right !
I should edit the main code too.
Code: [Select]

void receiveEvent(int howMany)
{
 char incoming[128];
 while(Wire.available() < howMany); // do nothing
   for (int i = 0; i < howMany; i++) {
       if(i < 128){                      
           incoming[i] = Wire.receive();  
           incoming[i+1] = '\0';
           Serial.print(incoming);}
       }
   }

Before I write the strcmp(), I have a question to ask. G1 and G28 are g-codes that the Reprap will be sending to Arduino and they are in this form:
G28 X0 Y0
G1 X10 Y10

What do you suggest a proper way of comparing the incoming data would be ?

AWOL

Code: [Select]
if(i < 128){                      
           incoming[i] = Wire.receive();  
           incoming[i+1] = '\0';

Yous still don't have a "incoming [128]".

Can we ease-up on the "20 questions" style now please?
"Pete, it's a fool looks for logic in the chambers of the human heart." Ulysses Everett McGill.
Do not send technical questions via personal messaging - they will be ignored.

Javaid

To be very honest, I never follow what you say. And I am pretty sure that the problem is on my end.

Will you please tell me where the problem is and where I went wrong (again  :~)

Go Up