1

I am trying to connect an LPS331AP pressure sensor to my ATtiny85, to read the pressure from it. My code works flawlessly on an Arduino Uno, but when making the relevant changes as suggested on multiple forums, I am getting errors that I don't quite know how to resolve. I am using Wire.h, twi.h, TinyWire.h and LPS.h libraries, to no avail.

I have tried editing the libraries to conform to the different function errors, and declare pins, but I cannot get it to work. I have reset everything, the code and libraries I use are shown below:

The code that I am trying to execute is shown below:

#include <TinyWire.h>
#include "USI_TWI_Master.h"

#include <LPS.h>

LPS ps;

void setup()
{
  TinyWire.begin();

  ps.enableDefault();
}

void loop()
{
  float pressure = ps.readPressureMillibars();
  float altitude = ps.pressureToAltitudeMeters(pressure);
  float temperature = ps.readTemperatureC();

  delay(100);
}

I expect the code to upload without error, then I can start writing code to process the data and do calculations on it. At the moment I get the following errors:

Arduino: 1.8.9 (Windows 7), Board: "ATtiny25/45/85, ATtiny85, Internal 8 MHz"

Build options changed, rebuilding all
C:\Program Files (x86)\Arduino\hardware\arduino\avr\libraries\Wire\src\utility\twi.c: In function 'twi_init':

C:\Program Files (x86)\Arduino\hardware\arduino\avr\libraries\Wire\src\utility\twi.c:76:16: error: 'SDA' undeclared (first use in this function)

   digitalWrite(SDA, 1);

                ^

C:\Program Files (x86)\Arduino\hardware\arduino\avr\libraries\Wire\src\utility\twi.c:76:16: note: each undeclared identifier is reported only once for each function it appears in

C:\Program Files (x86)\Arduino\hardware\arduino\avr\libraries\Wire\src\utility\twi.c:77:16: error: 'SCL' undeclared (first use in this function)

   digitalWrite(SCL, 1);

                ^

In file included from c:\program files (x86)\arduino\hardware\tools\avr\avr\include\avr\io.h:99:0,

                 from C:\Program Files (x86)\Arduino\hardware\arduino\avr\libraries\Wire\src\utility\twi.c:25:

C:\Program Files (x86)\Arduino\hardware\arduino\avr\libraries\Wire\src\utility\twi.c:80:7: error: 'TWSR' undeclared (first use in this function)

   cbi(TWSR, TWPS0);

       ^

C:\Program Files (x86)\Arduino\hardware\arduino\avr\libraries\Wire\src\utility\twi.c:80:3: note: in expansion of macro 'cbi'

   cbi(TWSR, TWPS0);

   ^

C:\Program Files (x86)\Arduino\hardware\arduino\avr\libraries\Wire\src\utility\twi.c:80:13: error: 'TWPS0' undeclared (first use in this function)

   cbi(TWSR, TWPS0);

             ^

C:\Program Files (x86)\Arduino\hardware\arduino\avr\libraries\Wire\src\utility\twi.c:80:3: note: in expansion of macro 'cbi'

   cbi(TWSR, TWPS0);

   ^

C:\Program Files (x86)\Arduino\hardware\arduino\avr\libraries\Wire\src\utility\twi.c:81:13: error: 'TWPS1' undeclared (first use in this function)

   cbi(TWSR, TWPS1);

             ^

C:\Program Files (x86)\Arduino\hardware\arduino\avr\libraries\Wire\src\utility\twi.c:81:3: note: in expansion of macro 'cbi'

   cbi(TWSR, TWPS1);

   ^

C:\Program Files (x86)\Arduino\hardware\arduino\avr\libraries\Wire\src\utility\twi.c:82:3: error: 'TWBR' undeclared (first use in this function)

   TWBR = ((F_CPU / TWI_FREQ) - 16) / 2;

   ^


In file included from c:\program files (x86)\arduino\hardware\tools\avr\avr\include\avr\io.h:99:0,

                 from C:\Program Files (x86)\Arduino\hardware\arduino\avr\libraries\Wire\src\utility\twi.c:25:

C:\Program Files (x86)\Arduino\hardware\arduino\avr\libraries\Wire\src\utility\twi.c:393:14: error: 'TWEN' undeclared (first use in this function)

   TWCR = _BV(TWEN) | _BV(TWIE) | _BV(TWEA) | _BV(TWINT);

              ^

C:\Program Files (x86)\Arduino\hardware\arduino\avr\libraries\Wire\src\utility\twi.c:393:26: error: 'TWIE' undeclared (first use in this function)

   TWCR = _BV(TWEN) | _BV(TWIE) | _BV(TWEA) | _BV(TWINT);

                          ^

C:\Program Files (x86)\Arduino\hardware\arduino\avr\libraries\Wire\src\utility\twi.c:393:38: error: 'TWEA' undeclared (first use in this function)

   TWCR = _BV(TWEN) | _BV(TWIE) | _BV(TWEA) | _BV(TWINT);

                                      ^

C:\Program Files (x86)\Arduino\hardware\arduino\avr\libraries\Wire\src\utility\twi.c:393:50: error: 'TWINT' undeclared (first use in this function)

   TWCR = _BV(TWEN) | _BV(TWIE) | _BV(TWEA) | _BV(TWINT);

                                                  ^

In file included from c:\program files (x86)\arduino\hardware\tools\avr\avr\include\compat\twi.h:36:0,

                 from C:\Program Files (x86)\Arduino\hardware\arduino\avr\libraries\Wire\src\utility\twi.c:27:

C:\Program Files (x86)\Arduino\hardware\arduino\avr\libraries\Wire\src\utility\twi.c: In function 'TWI_vect':

C:\Program Files (x86)\Arduino\hardware\arduino\avr\libraries\Wire\src\utility\twi.c:401:10: error: 'TWSR' undeclared (first use in this function)

   switch(TW_STATUS){

          ^

In file included from c:\program files (x86)\arduino\hardware\tools\avr\avr\include\avr\io.h:99:0,

                 from C:\Program Files (x86)\Arduino\hardware\arduino\avr\libraries\Wire\src\utility\twi.c:25:

C:\Program Files (x86)\Arduino\hardware\arduino\avr\libraries\Wire\src\utility\twi.c:401:10: error: 'TWS7' undeclared (first use in this function)

   switch(TW_STATUS){

          ^

C:\Program Files (x86)\Arduino\hardware\arduino\avr\libraries\Wire\src\utility\twi.c:401:10: error: 'TWS6' undeclared (first use in this function)

   switch(TW_STATUS){

          ^

C:\Program Files (x86)\Arduino\hardware\arduino\avr\libraries\Wire\src\utility\twi.c:401:10: error: 'TWS5' undeclared (first use in this function)

   switch(TW_STATUS){

          ^

C:\Program Files (x86)\Arduino\hardware\arduino\avr\libraries\Wire\src\utility\twi.c:401:10: error: 'TWS4' undeclared (first use in this function)

   switch(TW_STATUS){

          ^

C:\Program Files (x86)\Arduino\hardware\arduino\avr\libraries\Wire\src\utility\twi.c:401:10: error: 'TWS3' undeclared (first use in this function)

   switch(TW_STATUS){

          ^

C:\Program Files (x86)\Arduino\hardware\arduino\avr\libraries\Wire\src\utility\twi.c:406:7: error: 'TWDR' undeclared (first use in this function)

       TWDR = twi_slarw;

       ^

C:\Program Files (x86)\Arduino\hardware\arduino\avr\libraries\Wire\src\utility\twi.c:426:4: error: 'TWCR' undeclared (first use in this function)

    TWCR = _BV(TWINT) | _BV(TWSTA)| _BV(TWEN) ;

    ^

In file included from c:\program files (x86)\arduino\hardware\tools\avr\avr\include\avr\io.h:99:0,

                 from C:\Program Files (x86)\Arduino\hardware\arduino\avr\libraries\Wire\src\utility\twi.c:25:

C:\Program Files (x86)\Arduino\hardware\arduino\avr\libraries\Wire\src\utility\twi.c:426:15: error: 'TWINT' undeclared (first use in this function)

    TWCR = _BV(TWINT) | _BV(TWSTA)| _BV(TWEN) ;

               ^

C:\Program Files (x86)\Arduino\hardware\arduino\avr\libraries\Wire\src\utility\twi.c:426:28: error: 'TWSTA' undeclared (first use in this function)

    TWCR = _BV(TWINT) | _BV(TWSTA)| _BV(TWEN) ;

                            ^

C:\Program Files (x86)\Arduino\hardware\arduino\avr\libraries\Wire\src\utility\twi.c:426:40: error: 'TWEN' undeclared (first use in this function)

    TWCR = _BV(TWINT) | _BV(TWSTA)| _BV(TWEN) ;

                                        ^

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

This report would have more information with
"Show verbose output during compilation"
option enabled in File -> Preferences.

The libraries that I use are shown below. The .h and .c libraries are in my local project folder:

TinyWire.h:

/*****************************************************************************
    *
    *
    * File              TinyWire.h
    * Date              Saturday, 10/29/17
    * Composed by       lucullus
 *********************************************************************************/

#ifndef tiny_twi_h
#define tiny_twi_h
    #include <inttypes.h>

    //********** Master Error Codes **********//
    // Note these have been renumbered from the Atmel Apps Note. Most likely errors are now
    //      lowest numbers so they're easily recognized as LED flashes.
    #define USI_TWI_NO_DATA             0x08  // Transmission buffer is empty
    #define USI_TWI_DATA_OUT_OF_BOUND   0x09  // Transmission buffer is outside SRAM space
    #define USI_TWI_UE_START_CON        0x07  // Unexpected Start Condition
    #define USI_TWI_UE_STOP_CON         0x06  // Unexpected Stop Condition
    #define USI_TWI_UE_DATA_COL         0x05  // Unexpected Data Collision (arbitration)
    #define USI_TWI_NO_ACK_ON_DATA      0x02  // The slave did not acknowledge  all data
    #define USI_TWI_NO_ACK_ON_ADDRESS   0x01  // The slave did not acknowledge  the address
    #define USI_TWI_MISSING_START_CON   0x03  // Generated Start Condition not detected on bus
    #define USI_TWI_MISSING_STOP_CON    0x04  // Generated Stop Condition not detected on bus
    #define USI_TWI_BAD_MEM_READ        0x0A  // Error during external memory read
    #define USI_TWI_BUS_BUSY            0x0B  // Another Master is using the bus
    #define USI_TWI_ARBITRATION_LOST    0x0C  // The master lost the arbitration due to the transmission of another master

    //********** Class Definition **********//
    class TinyTwi
    {
        private:
        bool master_mode=false;
        bool temp_master_mode=false;
        uint8_t slave_addr=0;
        static void (*user_onRequest)(void);
        static void (*user_onReceive)(int);
        static void onRequestService(void);
        static void onReceiveService(int numBytes);

        public:
        TinyTwi();
        void begin();
        void begin(uint8_t I2C_SLAVE_ADDR);
        uint8_t read();
        uint8_t receive();
        uint8_t available();
        uint8_t send(uint8_t data);
        uint8_t write(uint8_t data);
        void beginTransmission(uint8_t slaveAddr);
        uint8_t endTransmission();
        uint8_t requestFrom(uint8_t slaveAddr, uint8_t numBytes);
        void end();

        void onReceive( void (*)(int) );
        void onRequest( void (*)(void) );
    };

    extern TinyTwi TinyWire;

#endif

LPS.h:

#ifndef LPS_h
#define LPS_h

#include <Arduino.h> // for byte data type

class LPS
{
  public:
    enum deviceType { device_331AP, device_25H, device_auto };
    enum sa0State { sa0_low, sa0_high, sa0_auto };

    // register addresses
    // Note: where register names differ between the register mapping table and
    // the register descriptions in the datasheets, the names from the register
    // descriptions are used here.
    enum regAddr
    {
      REF_P_XL                = 0x08,
      REF_P_L                 = 0x09,
      REF_P_H                 = 0x0A,

      WHO_AM_I                = 0x0F,

      RES_CONF                = 0x10,

      CTRL_REG1               = 0x20,
      CTRL_REG2               = 0x21,
      CTRL_REG3               = 0x22,
      CTRL_REG4               = 0x23, // 25H

      STATUS_REG              = 0x27,

      PRESS_OUT_XL            = 0x28,
      PRESS_OUT_L             = 0x29,
      PRESS_OUT_H             = 0x2A,

      TEMP_OUT_L              = 0x2B,
      TEMP_OUT_H              = 0x2C,

      FIFO_CTRL               = 0x2E, // 25H
      FIFO_STATUS             = 0x2F, // 25H

      AMP_CTRL                = 0x30, // 331AP

      RPDS_L                  = 0x39, // 25H
      RPDS_H                  = 0x3A, // 25H

      DELTA_PRESS_XL          = 0x3C, // 331AP
      DELTA_PRESS_L           = 0x3D, // 331AP
      DELTA_PRESS_H           = 0x3E, // 331AP


      // dummy addresses for registers in different locations on different devices;
      // the library translates these based on device type
      // value with sign flipped is used as index into translated_regs array

      INTERRUPT_CFG    = -1,
      INT_SOURCE       = -2,
      THS_P_L          = -3,
      THS_P_H          = -4,
      // update dummy_reg_count if registers are added here!


      // device-specific register addresses

      LPS331AP_INTERRUPT_CFG  = 0x23,
      LPS331AP_INT_SOURCE     = 0x24,
      LPS331AP_THS_P_L        = 0x25,
      LPS331AP_THS_P_H        = 0x26,

      LPS25H_INTERRUPT_CFG    = 0x24,
      LPS25H_INT_SOURCE       = 0x25,
      LPS25H_THS_P_L          = 0x30,
      LPS25H_THS_P_H          = 0x31,
    };

    LPS(void);

    bool init(deviceType device = device_auto, byte sa0 = sa0_auto);
    deviceType getDeviceType(void) { return _device; }
    byte getAddress(void) { return address; }

    void enableDefault(void);

    void writeReg(int reg, byte value);
    byte readReg(int reg);

    float readPressureMillibars(void);
    float readPressureInchesHg(void);
    int32_t readPressureRaw(void);
    float readTemperatureC(void);
    float readTemperatureF(void);
    int16_t readTemperatureRaw(void);

    static float pressureToAltitudeMeters(float pressure_mbar, float altimeter_setting_mbar = 1013.25);
    static float pressureToAltitudeFeet(float pressure_inHg, float altimeter_setting_inHg = 29.9213);

  private:
    deviceType _device; // chip type (331AP or 25H)
    byte address;

    static const int dummy_reg_count = 4;
    regAddr translated_regs[dummy_reg_count + 1]; // index 0 not used

    bool detectDeviceAndAddress(deviceType device, sa0State sa0);
    bool detectDevice(deviceType device);
    int testWhoAmI(byte address);
};

#endif

USI_TWI_Master.h:

/*****************************************************************************
*
* Atmel Corporation
*
* File              : USI_TWI_Master.h
* Compiler          : AVRGCC Toolchain version 3.4.2
* Revision          : $Revision: 992 $
* Date              : $Date: 2013-11-07 $
* Updated by        : $Author: Atmel $
*
* Support mail      : avr@atmel.com
*
* Supported devices : All device with USI module can be used.
*                     The example is written for the ATmega169, ATtiny26 and ATtiny2313
*
* AppNote           : AVR310 - Using the USI module as a TWI Master
*
* Description       : This is an implementation of an TWI master using
*                     the USI module as basis. The implementation assumes the AVR to
*                     be the only TWI master in the system and can therefore not be
*                     used in a multi-master system.
* Usage             : Initialize the USI module by calling the USI_TWI_Master_Initialise() 
*                     function. Hence messages/data are transceived on the bus using
*                     the USI_TWI_Start_Transceiver_With_Data() function. If the transceiver
*                     returns with a fail, then use USI_TWI_Get_Status_Info to evaluate the 
*                     couse of the failure.
*
****************************************************************************/
    #include<avr/io.h> 
//********** Defines **********//

// Defines controlling timing limits
#define TWI_FAST_MODE

#define SYS_CLK   4000.0  // [kHz]

#ifdef TWI_FAST_MODE               // TWI FAST mode timing limits. SCL = 100-400kHz
  #define T2_TWI    ((SYS_CLK *1300) /1000000) +1 // >1,3us
  #define T4_TWI    ((SYS_CLK * 600) /1000000) +1 // >0,6us

#else                              // TWI STANDARD mode timing limits. SCL <= 100kHz
  #define T2_TWI    ((SYS_CLK *4700) /1000000) +1 // >4,7us
  #define T4_TWI    ((SYS_CLK *4000) /1000000) +1 // >4,0us
#endif

// Defines controling code generating
//#define PARAM_VERIFICATION
//#define NOISE_TESTING
//#define SIGNAL_VERIFY

//USI_TWI messages and flags and bit masks
//#define SUCCESS   7
//#define MSG       0
/****************************************************************************
  Bit and byte definitions
****************************************************************************/
#define TWI_READ_BIT  0       // Bit position for R/W bit in "address byte".
#define TWI_ADR_BITS  1       // Bit position for LSB of the slave address bits in the init byte.
#define TWI_NACK_BIT  0       // Bit position for (N)ACK bit.

#define USI_TWI_NO_DATA             0x00  // Transmission buffer is empty
#define USI_TWI_DATA_OUT_OF_BOUND   0x01  // Transmission buffer is outside SRAM space
#define USI_TWI_UE_START_CON        0x02  // Unexpected Start Condition
#define USI_TWI_UE_STOP_CON         0x03  // Unexpected Stop Condition
#define USI_TWI_UE_DATA_COL         0x04  // Unexpected Data Collision (arbitration)
#define USI_TWI_NO_ACK_ON_DATA      0x05  // The slave did not acknowledge  all data
#define USI_TWI_NO_ACK_ON_ADDRESS   0x06  // The slave did not acknowledge  the address
#define USI_TWI_MISSING_START_CON   0x07  // Generated Start Condition not detected on bus
#define USI_TWI_MISSING_STOP_CON    0x08  // Generated Stop Condition not detected on bus

// Device dependant defines

#if defined(__AVR_AT90Mega169__) | defined(__AVR_ATmega169PA__) | \
    defined(__AVR_AT90Mega165__) | defined(__AVR_ATmega165__) | \
    defined(__AVR_ATmega325__) | defined(__AVR_ATmega3250__) | \
    defined(__AVR_ATmega645__) | defined(__AVR_ATmega6450__) | \
    defined(__AVR_ATmega329__) | defined(__AVR_ATmega3290__) | \
    defined(__AVR_ATmega649__) | defined(__AVR_ATmega6490__)
    #define DDR_USI             DDRE
    #define PORT_USI            PORTE
    #define PIN_USI             PINE
    #define PORT_USI_SDA        PORTE5
    #define PORT_USI_SCL        PORTE4
    #define PIN_USI_SDA         PINE5
    #define PIN_USI_SCL         PINE4
#endif

#if defined(__AVR_ATtiny25__) | defined(__AVR_ATtiny45__) | defined(__AVR_ATtiny85__) | \
    defined(__AVR_AT90Tiny26__) | defined(__AVR_ATtiny26__)
    #define DDR_USI             DDRB
    #define PORT_USI            PORTB
    #define PIN_USI             PINB
    #define PORT_USI_SDA        PORTB0
    #define PORT_USI_SCL        PORTB2
    #define PIN_USI_SDA         PINB0
    #define PIN_USI_SCL         PINB2
#endif

#if defined(__AVR_AT90Tiny2313__) | defined(__AVR_ATtiny2313__)
    #define DDR_USI             DDRB
    #define PORT_USI            PORTB
    #define PIN_USI             PINB
    #define PORT_USI_SDA        PORTB5
    #define PORT_USI_SCL        PORTB7
    #define PIN_USI_SDA         PINB5
    #define PIN_USI_SCL         PINB7
#endif

// General defines
#define TRUE  1
#define FALSE 0

//********** Prototypes **********//

void              USI_TWI_Master_Initialise( void );
 unsigned char USI_TWI_Start_Transceiver_With_Data( unsigned char * , unsigned char );
unsigned char USI_TWI_Get_State_Info( void );

Any suggestions on fixes will be highly appreciated.

Adam
  • 71
  • 9
  • 1
    Possible duplicate of [Need advice on ATtiny85 libraries, LPS.h and TinyWireM.h, I am getting "Undefined reference" errors](https://stackoverflow.com/questions/57101834/need-advice-on-attiny85-libraries-lps-h-and-tinywirem-h-i-am-getting-undefine) – theSealion Jul 19 '19 at 09:41
  • Old (related) post deleted. – Adam Jul 19 '19 at 09:46

1 Answers1

4

ATtiny85 doesn't have TWI. It has USI to implement TWI. Operations on USI is different from one on TWI, so are the registers. To modify the library, please refer to AVR310 and AVR312, which introduce how to use USI in TWI mode.

jerry_fuyi
  • 483
  • 4
  • 12
  • Cool, thank you very much Jerry, will have a look and revert – Adam Jul 19 '19 at 10:11
  • Firstly delete `#include ` since register names starting with `TW` doesn't exist on ATtiny85 (they are registers for TWI module but not USI module). Edit your question to show the compiler output. – jerry_fuyi Jul 19 '19 at 10:12
  • Ok, I have added the GCC USI library. I have updated the script, library and compiler output errors in the post. – Adam Jul 19 '19 at 11:38
  • It seems the library involves `PORTD` but your MCU doesn't have. Copy "USI_TWI_Master.h" to your project folder along with the corresponding C source file but without "main.c". Then modify your code, using `#include "USI_TWI_Master.h"` instead of `#include ` – jerry_fuyi Jul 19 '19 at 11:47
  • Another suggestion is that I think maybe TinyWire.h is enough. Try using `TinyTwi` methods to replace the ones used in TinyWire.cpp. Refer to doc. – jerry_fuyi Jul 19 '19 at 11:50
  • The key problem is that TWI and USI class interfaces are different. On the level of hardware, there are features that TWI has but USI doesn't implement. For software, class methods' names, parameters may be different. A bridge is needed. If you know how to use USI module and what each method in TWI does, you can implement a TWI class using USI module. But it's costing. I think the best way for you is to read documentations for twi.h and [Tinywire.h or USI_TWI_Master.h], then build a bridge between them. – jerry_fuyi Jul 19 '19 at 11:54
  • Ok, I did your last recommendation and updated the post again... basically back to the previous error. – Adam Jul 19 '19 at 11:59
  • I'm going to try and replace the current methods with TinyTwi methods next. – Adam Jul 19 '19 at 11:59
  • I've once used the USI module. It's complex since it integrates SPI, TWI and USART 3 buses. It's also difficult to understand the data structure used in example code in docs if you haven't learnt Data Structure. – jerry_fuyi Jul 19 '19 at 12:02
  • 1
    Well, if I were you, I would read the doc for the sensor then write the class by myself (I've learnt I2C and USI before, and have much experience on C++ programming). Go for it! – jerry_fuyi Jul 19 '19 at 12:10
  • I have a suspicion that is what it is coming down to. Thanks for your help! – Adam Jul 19 '19 at 12:17