Go Down

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

AWOL

Quote
please tell me where the problem is and where I went wrong

Code: [Select]
incoming[i+1] = '\0'
Right there, if "i" is ever 127.
You need to pay attention to array sizes, or all sorts of strange things will start to happen.
"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


Code: [Select]
incoming[i+1] = '\0'
Right there, if "i" is ever 127.
You need to pay attention to array sizes, or all sorts of strange things will start to happen.

This is one more issue. As I have mentioned before that the code will be coming in this form from Reprap to Arduino
G28 X0 Y0
G1 X10 Y10
What do you suggest I should put the value as "i" will never be 127  :smiley-roll:



PaulS

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

I'd really suggest that you do this one step at a time. Assure that you are indeed getting what you think you are.

Then, when you have a NULL terminated array of chars containing "G28 Xxx Yyy", you can look at the strtok function to get the first token ("G28" when the delimiter set is " "). Compare that token with the constants, using strcmp().

Javaid

All right, so this is fine now, right !
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);
        }
       
        }
    }


Assure that you are indeed getting what you think you are.

According to what I have written in the Reprap code, I am sending
Code: [Select]

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

How do you propose I assure that I am actually getting this? I was putting up LED to see that.

Nick Gammon

Your posts, Javaid, just don't agree with each other. For example:

Quote
char incoming[4]; // don't really know what the size of a g-code would be, so work on this number :P 


Then:

Quote
As I have mentioned before that the code will be coming in this form from Reprap to Arduino
G28 X0 Y0


So straight away you are expecting more than 4 bytes from the reprap?




I pointed out before that this:

Quote
Code: [Select]
void loop()
{
  Wire.beginTransmission (5);
  Wire.send ("G1");
  Wire.send ("G28");
  Wire.endTransmission();
}


Will send G1G28 in a single transmission. Thus if the LED flickers, it will do so for a microsecond or so. You changed it a few times and then went back to the very thing I said would not work. Why?





All right, so this is fine now, right !
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);
        }
       
        }
    }



The receiveEvent is told how many bytes have been received (the howMany argument). There is absolutely no point in doing this:

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

Wire.available() will be equal to howMany. That's how it works.

You are asking for help. But you are generally speaking just ignoring what we say:

Quote
To be very honest, I never follow what you say.
Please post technical questions on the forum, not by personal message. Thanks!

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

Javaid

:.

Quote
To be very honest, I never follow what you say.


This particular post was for AWOL. I was just telling him that I don't really understand what he says.

And to be honest, it is kind of like this, when someone tells me to do something, I try to do it and then ask whether I have done it right or not. In the meantime, I get some suggestion from someone else and I start working on that. And in the end, I am messing up everything (so stupid of me  :smiley-eek:)

Let's just do 1 step at a time then, please.

PaulS

Quote
The receiveEvent is told how many bytes have been received (the howMany argument). There is absolutely no point in doing this:

Does the argument tell how many have been received or how many are to be received? In other words, is the callback called only after all the data has been received, or is it called as soon as data starts arriving?

I put that wait code in there on the assumption that the callback was called as soon as data started to arrive.

Nick Gammon

Wire.available function does this:

Code: [Select]
uint8_t TwoWire::available(void)
{
  return rxBufferLength - rxBufferIndex;
}


And this is the end of the internal ISR:

Code: [Select]
  // set rx iterator vars
  rxBufferIndex = 0;
  rxBufferLength = numBytes;
  // alert user program
  user_onReceive(numBytes);


Given that rxBufferIndex is 0 then Wire.available will return numBytes, that being the number of bytes received.

Actually, looking in twi.c I see this case for the stop condition:

Code: [Select]
case TW_SR_STOP: // stop or repeated start condition received
      // put a null char after data if there's room
      if(twi_rxBufferIndex < TWI_BUFFER_LENGTH){
        twi_rxBuffer[twi_rxBufferIndex] = '\0';
      }
      // sends ack and stops interface for clock stretching
      twi_stop();
      // callback to user defined callback
      twi_onSlaveReceive(twi_rxBuffer, twi_rxBufferIndex);
      // since we submit rx buffer to "wire" library, we can reset it
      twi_rxBufferIndex = 0;
      // ack future responses and leave slave receiver state
      twi_releaseBus();
      break;


So I think I can say reasonably confidently that the OnReceive callback is not called the moment a byte or two is received, it is called on the stop condition, that is when nothing more is available in this "packet". So there is no real point in looping on Wire.available in any case.
Please post technical questions on the forum, not by personal message. Thanks!

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

Nick Gammon

#98
Aug 29, 2011, 01:13 am Last Edit: Aug 29, 2011, 01:16 am by Nick Gammon Reason: 1

Let's just do 1 step at a time then, please.


OK, I have a couple of test sketches. Connecting two Arduinos together (gnd, +5v, SDA, SCL) and running one on each you should see the inbuilt LED (pin 13) flash once a second.

Master, which sends G1 then G28:

Code: [Select]

// Author: Nick Gammon
// Date: 29 August 2011

#include <Wire.h>

#define reprap 6
#define slave 5

void setup ()
{
Wire.begin (reprap);
}

void loop()
{
 Wire.beginTransmission (slave);
 Wire.send ("G1");
 Wire.endTransmission();

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

 delay (1000);

}


Note the delay, so you have a chance to see the LED blink. Note the beginTransmission / endTransmission pairs. This was what I have been talking about for quite a few pages.


The slave:

Code: [Select]

// Author: Nick Gammon
// Date: 29 August 2011

#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 looks for a transmission starting with G1 or G28 (actually you should probably make it "G1 " and "G28 " but I'll leave that as an exercise.

It works. It isn't complicated.

Now please, if you change it, make sure you understand why you are changing it.
Please post technical questions on the forum, not by personal message. Thanks!

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

Nick Gammon


Does the argument tell how many have been received or how many are to be received?


It wouldn't know that anyway. This is a receiveEvent not a requestEvent. It gets what it gets, it can't know in advance how much that will be.
Please post technical questions on the forum, not by personal message. Thanks!

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

PaulS

Quote
It wouldn't know that anyway. This is a receiveEvent not a requestEvent. It gets what it gets, it can't know in advance how much that will be.

Not trying to argue. I'm just asking. The Wire.send() function buffer the data. Nothing gets sent until Wire,endTransmission gets called. At that time, the Wire instance knows how much data there is in the buffer, so the receive event could get called as soon as data starts coming in, and the function could be told how much data to expect. Your other post indicates that this is not the case, though.

If not, though, I wonder what the purpose of the Wire.available() function is. If the receive event handler is told how much data to receive, why is there another function to determine how much data there is to read?

Nick Gammon

Quote
At that time, the Wire instance knows how much data there is in the buffer, so the receive event could get called as soon as data starts coming in ...


Well they are at different ends. The sending end knows how much is in the buffer, the receiving end doesn't know how much to expect.

And in fact with the Wire.requestFrom the receiving end knows how much it requested, that won't necessarily be how much it gets (however it NAKs once the correct amount is received so it won't get more, but it might get less).

Quote
I wonder what the purpose of the Wire.available() function is.


I suppose it is really a helper function. You pull out a byte at a time with Wire.receive, so it tells you how much is left in the internal buffer.

Perhaps more importantly, the onRequest event doesn't supply howMany (unlike the onReceive event). So without Wire.available you don't know how much data you actually got when you requested it. Maybe you requested 10 bytes but got 5.
Please post technical questions on the forum, not by personal message. Thanks!

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

Javaid

Thanks a bunch for this useful information :)

I wasn't around as the Z-axis of the Reprap got jammed and had to disassemble almost half the machine (not that anyone asked).

I used the code with Master in Reprap and Slave in Arduino (without any change). Yes, I can see the LED flash every second. But

1- A single command is taking a lot of time to execute. I put in
G28 X0 Y0
G1 X50 Y50
and it took round about 1min 40 sec for the first command and almost the same for the second (give or take 5 sec).
Clearly, it is not good scenario for printing.

2- And the LED is not in sync with the commands. It is just blinking. Whether I give some commands or not, it just keeps on blinking :~
According to the coding, it should work properly with any string starting with G1 (or G28) regardless of what follows it.

Javaid

#103
Sep 01, 2011, 05:46 pm Last Edit: Sep 02, 2011, 01:54 am by Javaid Reason: 1
I removed the delays in the Reprap (Master) code and now the commands are getting executed at normal speed. I do understand why the delays were there but because of them the commands were taking a lot of time to execute. That is why I removed them.

But now the LED is continuously ON and whenever I send G1 or G28, it turns OFF and then ON back again after the execution. It does flicker very quickly after the execution of each command, understandably as there is no delay.

Is it possible to keep the LED in ON state as long as the G1 command is executed. In short, if I want the LED to remain ON as long as I am sending G1 and only to turn OFF (send 0) when it receives G28, how to do that?

Or let's say
G28 X0 Y0 (remain OFF as long as this is executed)
G1 X10 Y10 (remain ON as long as this is executed)

Wait for a string with G28 to turn OFF otherwise if a string of G1 is being received, stay ON.

You guys have been extremely patient with somebody like me who has the programming skills of a bag of rocks and I really appreciate that. But I am still not there yet, so please keep posting your valuable comments :)



Nick Gammon

I posted code that did exactly what you wanted (from the test Arduino). When it sent G1 it turned the LED on and when it sent G28 it turned it off.

Now you want help with code that you haven't posted. Sorry that's impossible.
Please post technical questions on the forum, not by personal message. Thanks!

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

Go Up