lucullusTheOnly / TinyWire

Composite Master and Slave I2C library for Atmels ATTiny microcontrollers
107 stars 26 forks source link

Is there a way to call a TinyWire() function that acts like the Wire.requestFrom()? function #8

Closed TRexosaur closed 6 years ago

TRexosaur commented 6 years ago

Hi,

I'm writing code to an AT Tiny 85. How I wrote the code is: I wrote it using the Wire library, and made it work on an Arduino Uno. Then, I changed all the Wire() functions to TinyWire() functions and tried uploading it to the 85. However, before the sketch uploads an error shows up, "TinyWire.requestFrom() is not an object under TinyTwi". Is there a parallel requestFrom() function I can call to get around this?

It may be that requestFrom() is actually supported and I've screwed something else up. Not sure. Any help is a godsend.

This is my first GitHub post, If I'm doing something wrong feel free to roast me :)

lucullusTheOnly commented 6 years ago

The requestFrom function is actually supported. Please post your code, because I don't know, what this error message means (especially in this case).

tatobari commented 6 years ago

I've been using this library during the past two weeks and it works great. @TRexosaur Any chance you could share the code where you import the library?

TRexosaur commented 6 years ago

Code: //From http://michael.lesauvage.name/cod4-nunchuk-leaner/ //I have changed Wire to TinyWire and Added software serial provision bc the 85 has no hardware serial.

//////////////////////////////////////////////////////////////////////////////// // // File: read_nunchuk_improved.pde // // Author: Mike LeSauvage (code base from Chad at Windmeadow labs). // // Description: This file has the code to allow the Arduino to read from a // Wii Nunchuk using a two-wire interface and pass that info // over the serial cable. // ////////////////////////////////////////////////////////////////////////////////

include

include

include

const int Rx = 3; const int Tx = 4; SoftwareSerial mySerial(Rx,Tx);

//////////////////////////////////////////////////////////////////////////////// // // Function: setup // // Description: This function is executed on Arduino boot. Pin 13 is set for // output (blinking light), serial comms speed is set, and // the two-wire interface is configured to communicate to the // Nunchuk. // // Parameters: None. // // Returns: Nothing. // //////////////////////////////////////////////////////////////////////////////// void setup() { pinMode(Rx,INPUT); pinMode(Tx,OUTPUT);

pinMode(13, OUTPUT); mySerial.begin(19200);

TinyWire.begin(); //Join I2C bus as master (since no address specified). TinyWire.beginTransmission(0x52); //0x52 is Nunchuk's address. TinyWire.send(0x40); //Handshake part I TinyWire.send(0x00); //Handshake part II TinyWire.endTransmission();

}

//////////////////////////////////////////////////////////////////////////////// // // Function: loop // // Description: This is the function called continually as the Arduino executes. // For this program, it reads six bytes from the Nunchuk, decodes // each one as it arrives, adds packet info, and sends them over // the serial port. // // Parameters: None. // // Returns: Nothing. // //////////////////////////////////////////////////////////////////////////////// void loop() { int count=0; static int ledVal=LOW; uint8_t buffer[6]; //Buffer of unigned bytes for response.

TinyWire.requestFrom(0x52, 6); //Request 6 bytes from Nunchuk; while(TinyWire.available() && count<6) { buffer[count]=(TinyWire.receive()^0x17) + 0x17; //Decode byte. count++; } mySerial.print(""); //Indicate start of data with a for(count=0; count<6; count++) { mySerial.print(buffer[count], DEC); //Send in base-10. mySerial.print("-"); //Indicate end of number. } mySerial.print("-"); //Report error. while(TinyWire.available()) //Flush the buffer. TinyWire.receive(); TinyWire.beginTransmission(0x52); //Reset for new data by sending 0x00. TinyWire.send(0x00); TinyWire.endTransmission(); delay(20); //Approximate read rate of 50hz. ledVal=ledVal^0x01; //Blink after each send. digitalWrite(13, ledVal); }

In my first post, I claimed to be experiencing a certain error with requestFrom(). Today, I uploaded the sketch again. The error it gives is,

"exit status 1 'class TinyTwi' has no member named 'receive' ".

To me, this means I was sloppy when I wrote down the error message the first time around. I was fed up at the time and I paraphrased. However, entertain that this was not the case, and some unknown modification I just made caused the change in error messages if you think that will lead somewhere. If not I'd say:

exit status 1 'class TinyTwi' has no member named 'receive'

is the true error message.

lucullusTheOnly commented 6 years ago

There is really no function TinyWire.receive(), but neither in the Wire library. The Arduino reference says, that send and receive were used a time ago, but changed to write and read to match other communication libraries. So I think it should be TinyWire.read(), which reads a byte from the receiving buffer, deletes it from there and returns it for further use. Should solve your error.

But there you have a point. I also used send() instead of write(). So I will push a new version, that includes wrapper functions to support all these calls. With this we will be in line with the Arduino libraries and we can still use the older code.

lucullusTheOnly commented 6 years ago

I tried your code in my IDE and there is another problem:

It seems that the SoftwareSerial library uses the PINCHANGE interrupt, which TinyWire uses to catch the stop conditions. In your code you only use the master functionality. Maybe it is sufficient for you to use the old TinyWireM library (it has only master capability). I think that library works totally without interrupts.

Note: I don't know what version of the library do you use. 3 days ago I pushed a new version, were I disabled the definition for NOISE_TESTING in twi.h, since it triggered false when the library was used as a pure master, effectively blocking itself after the first transmission. If you have an older version, you can simple comment the NOISE_TESTING definition in twi.h

TRexosaur commented 6 years ago

I took your advice and switched to TinyWireM. I've included the next paragraph in case its useful for you, but otherwise just ignore it.

I have the new version of TinyWire in which you disabled NOISE_TESTING. With the code as it was posted above but with receive() changed to read(), the following error appears just as the green upload sketch bar gets full:

"libraries\SoftwareSerial\SoftwareSerial.cpp.o (symbol from plugin): In function `SoftwareSerial::read()':

(.text+0x0): multiple definition of `__vector_2'

libraries\TinyWire\twi.cpp.o (symbol from plugin):(.text+0x0): first defined here

collect2.exe: error: ld returned 1 exit status

exit status 1 Error compiling for board ATtiny25/45/85."

However, I don't really care because I switched my library to TinyWireM and the sketch uploads(Note that TinyWireM is older than yours and still thinks that receive() is receive(), no read() here!)

So I've got an uploaded sketch and now, the Serial Monitor is funky, I am sure it is because my pinout is incorrect. Here is what the Serial Monitor reads:

46-46-46-46-46-46--46-46-46-46-46-46⸮*46-46-46-46-46-46--

The and - are part of my code. The indicates the start of a packet of six new bytes, and the - indicates the start of a new byte. There is a second - after the sixth "byte" in each sequence. There is a comment in the code saying that this indicates an error. Michael LeSauvage, from whom I took this code, is responsible for this whole section and I hardly understand it.

What I want to fix here is simple: The nunchuk uses six bytes to send its x/y/z joystick, x/y/z accelerometer, and Z/C button values. The only one I am interested in (for now) is the y-joystick data, which is sent in the second byte. (If you want to know more check the table at the end of this pdf: https://free-electrons.com/labs/doc/nunchuk.pdf )

Why might all of my bytes be read a 46? They are unresponsive to nunchuck control. I had it responsive on an UNO, so I know LeSauvage's code is valid. This is how I have connected my 85:

wired to pin 10, set High | AT | wired to UNO's 5V set to Rx, not wired up | tiny | not wired up set to Tx, wired to UNO's D1/Tx pin | 85 | Wired to nunchuck SCL wired to UNO's gnd | | Wired to nunchuk SDA

My nunchuk is powered by the UNO's 5V and gnd.

The other possibility is that my UNO is somehow interrupting the serial communication. At first, my UNO had the example ArduinoIDE sketch on it, but I plugged in another UNO with a blank sketch and just set pin 10 to output, and then set it high. The same serial monitor showed up.

Take a look at the SCL/SDA pins: I have them connected to the 85's PWM output pins... I saw this somewhere online but maybe the SCL/SDA lines are supposed to go in via the Analog input pins.

TRexosaur commented 6 years ago

Above, I tried to include a diagram of my AT Tiny wiring based off this photo:

but When I post it takes away my spaces and makes it a blob of text

wired to pin 10, set High | AT | wired to UNO's 5V set to Rx, not wired up | tiny | not wired up set to Tx, wired to UNO's D1/Tx pin | 85 | Wired to nunchuck SCL wired to UNO's gnd | | Wired to nunchuk SDA

lucullusTheOnly commented 6 years ago

At the ATTiny you have to connect pin 5 with SDA and pin 7 with SCL (look in the datasheet for this information). Have you checked, if the communication with the nunchuck really is functional? For example you could take the joystick value and switch/dimm an LED on pin 6 (pin 1 in code) with it, so ensure, that the values are correctly send to your ATTiny.

Since this isn't about the TinyWire library anymore, you will be better of asking questions either directly about TinyWireM on it's github page or at a side like arduino.stackexchange.com. I will be closing this issue.

TRexosaur commented 6 years ago

@tatobari I have tried getting in contact with you to discuss how to get my code to work, but I can't find your email! Please try to reach me at 42jeffs@gmail.com. Also, Sorry for posting in a now closed thread, but I've still got issues. It isn't my nunchuck, I know it works bc I can dim an LED with it.

tatobari commented 6 years ago

@lucullusTheOnly We're still working on this issue. We'll post the progress as we make some. We'll let you know! @TRexosaur ordered a few components and they are delayed. We will resume this as soon as he has the components and can share a few pictures.

Meanwhile, here's the marked-down code he posted:

//From http://michael.lesauvage.name/cod4-nunchuk-leaner/
//I have changed Wire to TinyWire and Added software serial provision bc the 85 has no hardware serial.

////////////////////////////////////////////////////////////////////////////////
//
// File: read_nunchuk_improved.pde
//
// Author: Mike LeSauvage (code base from Chad at Windmeadow labs).
//
// Description: This file has the code to allow the Arduino to read from a
// Wii Nunchuk using a two-wire interface and pass that info
// over the serial cable.
//
////////////////////////////////////////////////////////////////////////////////
#include <string.h>
#include <TinyWire.h>
#include <SoftwareSerial.h>
const int Rx = 3;
const int Tx = 4;
SoftwareSerial mySerial(Rx,Tx);

////////////////////////////////////////////////////////////////////////////////
//
// Function: setup
//
// Description: This function is executed on Arduino boot. Pin 13 is set for
// output (blinking light), serial comms speed is set, and
// the two-wire interface is configured to communicate to the
// Nunchuk.
//
// Parameters: None.
//
// Returns: Nothing.
//
////////////////////////////////////////////////////////////////////////////////
void setup()
{
    pinMode(Rx,INPUT);
    pinMode(Tx,OUTPUT);

    pinMode(13, OUTPUT);
    mySerial.begin(19200);

    TinyWire.begin(); //Join I2C bus as master (since no address specified).
    TinyWire.beginTransmission(0x52); //0x52 is Nunchuk's address.
    TinyWire.send(0x40); //Handshake part I
    TinyWire.send(0x00); //Handshake part II
    TinyWire.endTransmission();
}

////////////////////////////////////////////////////////////////////////////////
//
// Function: loop
//
// Description: This is the function called continually as the Arduino executes.
// For this program, it reads six bytes from the Nunchuk, decodes
// each one as it arrives, adds packet info, and sends them over
// the serial port.
//
// Parameters: None.
//
// Returns: Nothing.
//
////////////////////////////////////////////////////////////////////////////////
void loop()
{
    int count=0;
    static int ledVal=LOW;
    uint8_t buffer[6]; //Buffer of unigned bytes for response.

    TinyWire.requestFrom(0x52, 6); //Request 6 bytes from Nunchuk;
    while(TinyWire.available() && count<6)  {
        buffer[count]=(TinyWire.receive()^0x17) + 0x17; //Decode byte.
        count++;
    }
    mySerial.print("*"); //Indicate start of data with a *

    for(count=0; count<6; count++){
        mySerial.print(buffer[count], DEC); //Send in base-10.
        mySerial.print("-"); //Indicate end of number.
    }
    mySerial.print("-"); //Report error.
    while(TinyWire.available()) //Flush the buffer.
    TinyWire.receive();
    TinyWire.beginTransmission(0x52); //Reset for new data by sending 0x00.
    TinyWire.send(0x00);
    TinyWire.endTransmission();
    delay(20); //Approximate read rate of 50hz.
    ledVal=ledVal^0x01; //Blink after each send.
    digitalWrite(13, ledVal);
}