troubleshooting ATtiny25 i2c slave

Go To Last Post
9 posts / 0 new
Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I'm attempting to troubleshoot a Tiny25 that's supposed to be operating as an I2C slave.

 

I got the i2c slave library code for the Tiny25 from this article by Adam Honse -- http://www.instructables.com/id/ATTiny-USI-I2C-The-detailed-in-depth-and-infor (specifically, from the author's Github repo at https://github.com/CalcProgrammer1/Stepper-Motor-Controller/tree/master/UnipolarStepperDriver )

 

The Tiny25 is on a breadboard, being programmed via ISP using Atmel Studio 7 and a JTAGice mkII. Both SDA and SCL are being pulled high by 6.8k resistors.

 

To test it, I found an Arduino sketch that iterates through addresses 8 through 120, and reports those that appear to belong to a device on the I2C bus. This part is running on an Arduino Uno & works just fine... if I connect its SCL & SDA lines to the SCL and SDA pins on an I2C eeprom (and pull the lines high through a pair of 6.8k resistors), it instantly finds the eeprom and outputs the address.

 

To repeat: The Arduino running the enumerate.ino sketch, when connected to an I2C eeprom, is my "known good" configuration that has been personally seen working.

 

I then disconnected the wires from the I2C eeprom, and connected them to pins 5 and 7 (SDA and SCK) on the Tiny25 & re-ran it. This time, the test master saw nothing when it probed the I2C bus.

 

Before I try doing anything really hardcore, I'd appreciate if someone could quickly sanity-check the code and confirm that the master test sketch is actually doing something that SHOULD be eliciting a detectable response from the slave code running on the Tiny25.

 

 

 

Details that might be important:

  • I un-checked the "CKDIV8" fuse for the Tiny25 in Atmel Studio & updated the settings. As far as I know, this means the Tiny25 is running at 8MHz.
  • Both the Arduino and the Tiny25 are running at 5v. The Arduino is USB-powered, the Tiny25 is powered by a 5v regulated switching power supply. Ground of both is connected.
  • I'm quite confident that the ISR subroutine in usi_i2c_slave.c is never firing. I added a line to set PORTB &= ~(1<<3) (in lieu of the PINB = (1<<3) toggle) to cause the LED on pin 2 (PB3) to permanently light up after ISR executes at least once... the LED never lights up.
  • I know there's a signal on pins 7 and 5 coming from the Arduino... I can hear it with the logic probe. At this moment, I can't say anything about the quality of that signal, besides confirm that the total wire length between the Arduino and Tiny25 is about 9 inches & both wires are pulled high through 6.8k resistors.

 

Assuming I'm probing for something that SHOULD be eliciting a response, I'm open to ideas for what to try next.

 

 

 

The four relevant sourcecode files (listed at the end of this post to avoid burying my actual question amidst an ocean of visual noise):

 

  • enumerate.ino -- an Arduino sketch running on an Arduino Uno that iterates through addresses 8 through 120 & reports those where an i2c device appears to be responding.
  • main.c -- my program, which uses CalcProgrammer1's usi_i2c_slave library
  • usi_i2c_slave.c -- modified to toggle pin B3 (connected to a LED through a resistor) to provide visual evidence of activity
  • usi_i2c_slave.h -- modified to add definition for __AVR_ATtiny25__

 

 

 

enumerate.ino:

#include <Wire.h>
#include <Arduino.h>

const int address = 0x40;

void scan() {
	Serial.println ();
  Serial.println ("I2C scanner. Scanning ...");
  byte count = 0;

  Wire.begin();
  digitalWrite(LED_BUILTIN, HIGH);
  for (byte i = 8; i < 120; i++)
  {
    Wire.beginTransmission (i);
    if (Wire.endTransmission () == 0)
      {
      Serial.print ("Found address: ");
      Serial.print (i, DEC);
      Serial.print (" (0x");
      Serial.print (i, HEX);
      Serial.println (")");
      count++;
      delay (1);  // maybe unneeded?
      } // end of good response
  } // end of for loop
  digitalWrite(LED_BUILTIN, LOW);
  delay(500);
  if (count > 0) {
  	digitalWrite(LED_BUILTIN, HIGH);
  }
  delay(3000);
  digitalWrite(LED_BUILTIN, LOW);
  delay(1000);
  Serial.println ("Done.");
  Serial.print ("Found ");
  Serial.print (count, DEC);
  Serial.println (" device(s).");
}

void setup() {
  Serial.begin (115200);
  pinMode(LED_BUILTIN, OUTPUT);

}  // end of setup

void loop() {
	scan();
	delay(5000);
}

 

main.c:

 

#include <avr/io.h>
#include "usi_i2c_slave.h"

extern char* USI_Slave_register_buffer[];

void setup() {
	DDRB |= (1<<3);
	PORTB &= ~(1<<3);
	PINB |= (1<<3);

	// as I understand C, the elements of USI_Slave_register_buffer are pointers to unsigned chars.
	// The code I have below should, theoretically, cause it to return 0xf0 when asked to read register 0, 0xca when asked to read register 1, and so on.
	unsigned char uno = 0xf0;
	USI_Slave_register_buffer[0] = (unsigned char*)&uno;
	unsigned char dos = 0xca;
	USI_Slave_register_buffer[1] = (unsigned char*)&dos;
	unsigned char tres = 0x69;
	USI_Slave_register_buffer[2] = (unsigned char*)&tres;
	unsigned char cuatro = 0x42;
	USI_Slave_register_buffer[3] = (unsigned char*)&cuatro;

	// set the address we'll be responding to
	USI_I2C_Init(0x40);
}

int main(void) {
    setup();
    while (1){
		// nothing to do here... all the I2C work is done by the library using interrupts.
    }
}

 

usi_i2c_slave.h (with modifications to add definition for tiny25):

 

/*-----------------------------------------------------*\
|  USI I2C Slave Driver                                 |
|                                                       |
| This library provides a robust, interrupt-driven I2C  |
| slave implementation built on the ATTiny Universal    |
| Serial Interface (USI) hardware.  Slave operation is  |
| implemented as a register bank, where each 'register' |
| is a pointer to an 8-bit variable in the main code.   |
| This was chosen to make I2C integration transparent   |
| to the mainline code and making I2C reads simple.     |
| This library also works well with the Linux I2C-Tools |
| utilities i2cdetect, i2cget, i2cset, and i2cdump.     |
|                                                       |
| Adam Honse (GitHub: CalcProgrammer1) - 7/29/2012      |
|            -calcprogrammer1@gmail.com                 |
\*-----------------------------------------------------*/
#ifndef USI_I2C_SLAVE_H
#define USI_I2C_SLAVE_H

#include <avr/io.h>
#include <avr/interrupt.h>

//Microcontroller Dependent Definitions

#if defined (__AVR_ATtiny25__)
	#define DDR_USI			DDRB
	#define PORT_USI		PORTB
	#define PIN_USI			PINB
	#define PORT_USI_SDA	PB0
	#define PORT_USI_SCL	PB2
	#define PIN_USI_SDA		PINB0
	#define PIN_USI_SCL		PINB2
#endif

#if defined (__AVR_ATtiny24__) | \
	defined (__AVR_ATtiny44__) | \
	defined (__AVR_ATtiny84__)
	#define DDR_USI			DDRA
	#define PORT_USI		PORTA
	#define PIN_USI			PINA
	#define PORT_USI_SDA	PA6
	#define PORT_USI_SCL	PA4
	#define PIN_USI_SDA		PINA6
	#define PIN_USI_SCL		PINA4
#endif

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

//USI I2C Initialize
//  address - If slave, this parameter is the slave address
void USI_I2C_Init(char address);

#endif

and usi_i2c_slave.c (with small modification by me to toggle the state of a LED connected (through a resistor) to pin 2 (B3) on the tiny25):

 

/*-----------------------------------------------------*\
|  USI I2C Slave Driver                                 |
|                                                       |
| This library provides a robust, interrupt-driven I2C  |
| slave implementation built on the ATTiny Universal    |
| Serial Interface (USI) hardware.  Slave operation is  |
| implemented as a register bank, where each 'register' |
| is a pointer to an 8-bit variable in the main code.   |
| This was chosen to make I2C integration transparent   |
| to the mainline code and making I2C reads simple.     |
| This library also works well with the Linux I2C-Tools |
| utilities i2cdetect, i2cget, i2cset, and i2cdump.     |
|                                                       |
| Adam Honse (GitHub: CalcProgrammer1) - 7/29/2012      |
|            -calcprogrammer1@gmail.com                 |
\*-----------------------------------------------------*/

#include "usi_i2c_slave.h"

char usi_i2c_slave_internal_address;
char usi_i2c_slave_address;
char usi_i2c_mode;

///////////////////////////////////////////////////////////////////////////////////////////////////
////USI Slave States///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////////

#define USI_SLAVE_REGISTER_COUNT 8

// The I2C register file is stored as an array of pointers, point these to whatever your I2C registers
// need to read/write in your code.  This abstracts the buffer and makes it easier to write directly
// to values in your code.
char* USI_Slave_register_buffer[USI_SLAVE_REGISTER_COUNT];
char  USI_Slave_internal_address = 0;
char  USI_Slave_internal_address_set = 0;

enum

{

  USI_SLAVE_CHECK_ADDRESS,
  USI_SLAVE_SEND_DATA,
  USI_SLAVE_SEND_DATA_ACK_WAIT,
  USI_SLAVE_SEND_DATA_ACK_CHECK,

  USI_SLAVE_RECV_DATA_WAIT,

  USI_SLAVE_RECV_DATA_ACK_SEND

} USI_I2C_Slave_State;

/////////////////////////////////////////////////
////USI Register Setup Values////////////////////
/////////////////////////////////////////////////

#define USI_SLAVE_COUNT_ACK_USISR			0b01110000 | (0x0E << USICNT0)	//Counts one clock (ACK)
#define USI_SLAVE_COUNT_BYTE_USISR			0b01110000 | (0x00 << USICNT0)	//Counts 8 clocks (BYTE)
#define USI_SLAVE_CLEAR_START_USISR			0b11110000 | (0x00 << USICNT0)  //Clears START flag
#define USI_SLAVE_SET_START_COND_USISR		0b01110000 | (0x00 << USICNT0)
#define USI_SLAVE_SET_START_COND_USICR		0b10101000
#define USI_SLAVE_STOP_DID_OCCUR_USICR		0b10111000
#define USI_SLAVE_STOP_NOT_OCCUR_USICR		0b11101000

/////////////////////////////////////////////////
////USI Direction Macros/////////////////////////
/////////////////////////////////////////////////

#define USI_SET_SDA_OUTPUT()	{ DDR_USI |=  (1 << PORT_USI_SDA); }
#define USI_SET_SDA_INPUT() 	{ DDR_USI &= ~(1 << PORT_USI_SDA); }

#define USI_SET_SCL_OUTPUT()	{ DDR_USI |=  (1 << PORT_USI_SCL); }
#define USI_SET_SCL_INPUT() 	{ DDR_USI &= ~(1 << PORT_USI_SCL); }

#define USI_SET_BOTH_OUTPUT()	{ DDR_USI |= (1 << PORT_USI_SDA) | (1 << PORT_USI_SCL); }
#define USI_SET_BOTH_INPUT() 	{ DDR_USI &= ~((1 << PORT_USI_SDA) | (1 << PORT_USI_SCL)); }

////////////////////////////////////////////////////////////////////////////////////////////////////

void USI_I2C_Init(char address)
{
	PORT_USI &= ~(1 << PORT_USI_SCL);
	PORT_USI &= ~(1 << PORT_USI_SDA);

	usi_i2c_slave_address = address;

	USI_SET_BOTH_INPUT();

	USICR = (1 << USISIE) | (0 << USIOIE) | (1 << USIWM1) | (0 << USIWM0) | (1 << USICS1) | (0 << USICS0) | (0 << USICLK) | (0 << USITC);
	USISR = (1 << USISIF) | (1 << USIOIF) | (1 << USIPF) | (1 << USIDC);
}

/////////////////////////////////////////////////////////////////////////////////
// ISR USI_START_vect - USI Start Condition Detector Interrupt                 //
//                                                                             //
//  This interrupt occurs when the USI Start Condition Detector detects a      //
//  start condition.  A start condition marks the beginning of an I2C          //
//  transmission and occurs when SDA has a high->low transition followed by an //
//  SCL high->low transition.  When a start condition occurs, the I2C slave    //
//  state is set to check address mode and the counter is set to wait 8 clocks //
//  (enough for the address/rw byte to be transmitted) before overflowing and  //
//  triggering the first state table interrupt.  If a stop condition occurs,   //
//  reset the start condition detector to detect the next start condition.     //
/////////////////////////////////////////////////////////////////////////////////

ISR(USI_START_vect)

{

	PINB = (1<<3); // toggle the LED to show activity

	USI_I2C_Slave_State = USI_SLAVE_CHECK_ADDRESS;

	USI_SET_SDA_INPUT();

	// wait for SCL to go low to ensure the Start Condition has completed (the

	// start detector will hold SCL low ) - if a Stop Condition arises then leave

	// the interrupt to prevent waiting forever - don't use USISR to test for Stop

	// Condition as in Application Note AVR312 because the Stop Condition Flag is

	// going to be set from the last TWI sequence

	while((PIN_USI & (1 << PIN_USI_SCL)) && !((PIN_USI & (1 << PIN_USI_SDA))));

	if(!(PIN_USI & (1 << PIN_USI_SDA)))

	{

		// a Stop Condition did not occur

		USICR = USI_SLAVE_STOP_NOT_OCCUR_USICR;

	}

	else

	{
		// a Stop Condition did occur

    	USICR = USI_SLAVE_STOP_DID_OCCUR_USICR;

	}

	USISR = USI_SLAVE_CLEAR_START_USISR;

}

/////////////////////////////////////////////////////////////////////////////////
// ISR USI_OVERFLOW_vect - USI Overflow Interrupt                              //
//                                                                             //
//  This interrupt occurs when the USI counter overflows.  By setting this     //
//  counter to 8, the USI can be commanded to wait one byte length before      //
//  causing another interrupt (and thus state change).  To wait for an ACK,    //
//  set the counter to 1 (actually -1, or 0x0E) it will wait one clock.        //
//  This is used to set up a state table of I2C transmission states that fits  //
//  the I2C protocol for proper transmission.                                  //
/////////////////////////////////////////////////////////////////////////////////

ISR(USI_OVERFLOW_vect)

{
	PINB = (1<<3); // toggle the LED to show activity
	switch (USI_I2C_Slave_State)

	{
		/////////////////////////////////////////////////////////////////////////
		// Case USI_SLAVE_CHECK_ADDRESS                                        //
		//                                                                     //
		//  The first state after the start condition, this state checks the   //
		//  received byte against the stored slave address as well as the      //
		//  global transmission address of 0x00.  If there is a match, the R/W //
		//  bit is checked to branch either to sending or receiving modes.     //
		//  If the address was not for this device, the USI system is          //
		//  re-initialized for start condition.                                //
		/////////////////////////////////////////////////////////////////////////

		case USI_SLAVE_CHECK_ADDRESS:

			if((USIDR == 0) || ((USIDR >> 1) == usi_i2c_slave_address))

			{
				if (USIDR & 0x01)

				{
					USI_I2C_Slave_State = USI_SLAVE_SEND_DATA;

				}

				else

				{
					USI_Slave_internal_address_set = 0;
					USI_I2C_Slave_State = USI_SLAVE_RECV_DATA_WAIT;

				}

				//Set USI to send ACK

				USIDR = 0;

				USI_SET_SDA_OUTPUT();

				USISR = USI_SLAVE_COUNT_ACK_USISR;
			}

			else

			{
				//Set USI to Start Condition Mode

				USICR = USI_SLAVE_SET_START_COND_USICR;

				USISR = USI_SLAVE_SET_START_COND_USISR;
			}

			break;

		/////////////////////////////////////////////////////////////////////////
		// Case USI_SLAVE_SEND_DATA_ACK_WAIT                                   //
		//                                                                     //
		//  Wait 1 clock period for the master to ACK or NACK the sent data	   //
		//  If master NACK's, it means that master doesn't want any more data. //
		/////////////////////////////////////////////////////////////////////////
		case USI_SLAVE_SEND_DATA_ACK_WAIT:

			//After sending, immediately shut off PORT = 1 to prevent driving
			//the line high (I2C should *NEVER* drive high, and could damage
			//connected devices if operating at different voltage levels)
			PORT_USI &= ~(1 << PORT_USI_SDA);

			USI_I2C_Slave_State = USI_SLAVE_SEND_DATA_ACK_CHECK;
			USI_SET_SDA_INPUT();
			USISR = USI_SLAVE_COUNT_ACK_USISR;
			break;

		/////////////////////////////////////////////////////////////////////////
		// Case USI_SLAVE_SEND_DATA_ACK_CHECK                                  //
		//                                                                     //
		//  Check USIDR to see if master sent ACK or NACK.  If NACK, set up    //
		//  a reset to START conditions, if ACK, fall through into SEND_DATA   //
		//  to continue sending data.                                          //
		/////////////////////////////////////////////////////////////////////////
		case USI_SLAVE_SEND_DATA_ACK_CHECK:

			if(USIDR)
			{
				//The master sent a NACK, indicating that it will not accept
				//more data.  Reset into START condition state
				USICR = USI_SLAVE_SET_START_COND_USICR;
				USISR = USI_SLAVE_SET_START_COND_USISR;
				return;
			}
			//else: fall through into SEND_DATA

		/////////////////////////////////////////////////////////////////////////
		// Case USI_SLAVE_SEND_DATA                                            //
		//                                                                     //
		//  Set USIDR to the data to be sent, then set up SDA registers to     //
		//  enable data transmission in the next 8 clocks.  Set to wait 8      //
		//  clocks and proceed to wait for ACK.                                //
		/////////////////////////////////////////////////////////////////////////
		case USI_SLAVE_SEND_DATA:

			if(USI_Slave_internal_address <= USI_SLAVE_REGISTER_COUNT)
			{
				USIDR = *(USI_Slave_register_buffer[USI_Slave_internal_address]);
			}
			else
			{
				USIDR = 0x00;
			}
			USI_Slave_internal_address++;

			USI_I2C_Slave_State = USI_SLAVE_SEND_DATA_ACK_WAIT;

			//To send data, DDR for SDA must be 1 (Output) and PORT for SDA
			//must also be 1 (line drives low on USIDR MSB = 0 or PORT = 0)

			USI_SET_SDA_OUTPUT();
			PORT_USI |= (1 << PORT_USI_SDA);

			USISR = USI_SLAVE_COUNT_BYTE_USISR;

			break;

		/////////////////////////////////////////////////////////////////////////
		// Case USI_SLAVE_RECV_DATA_WAIT                                       //
		//                                                                     //
		//  Prepares to wait 8 clocks to receive a data byte from the master.  //
		/////////////////////////////////////////////////////////////////////////

		case USI_SLAVE_RECV_DATA_WAIT:

			USI_I2C_Slave_State = USI_SLAVE_RECV_DATA_ACK_SEND;

			USI_SET_SDA_INPUT();

			USISR = USI_SLAVE_COUNT_BYTE_USISR;

			break;

		/////////////////////////////////////////////////////////////////////////
		// Case USI_SLAVE_RECV_DATA_ACK_SEND                                   //
		//                                                                     //
		//  After waiting for the master to finish transmission, this reads    //
		//  USIDR into either the i2c buffer or internal address, then sends   //
		//  an acknowledgement to the master.                                  //
		/////////////////////////////////////////////////////////////////////////

		case USI_SLAVE_RECV_DATA_ACK_SEND:

			USI_I2C_Slave_State = USI_SLAVE_RECV_DATA_WAIT;

			if(USI_Slave_internal_address_set == 0)
			{
				USI_Slave_internal_address = USIDR;
				USI_Slave_internal_address_set = 1;
			}
			else if(USI_Slave_internal_address <= USI_SLAVE_REGISTER_COUNT)
			{
				*(USI_Slave_register_buffer[USI_Slave_internal_address]) = USIDR;
			}

			USIDR = 0;

			USI_SET_SDA_OUTPUT();

			USISR = USI_SLAVE_COUNT_ACK_USISR;

			break;

	}

}

 

There's no place like ~/

Last Edited: Tue. May 29, 2018 - 02:39 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 1

Install an Arduino TinyCore on your t85. Ii am sure that you own the 8k version of the t25.
Develop your Slave code with TinyWireS library.
Test with Master code with the Wire library on Uno.
.
You can reverse the situation with TinyWireM on the t85 and a Wire Slave on the Uno.
.
Then you can replace the TinyWireS application with an AS7 project. Develop on t85. Final tests on t25.
You have still got all your Uno Wire Master sketches for testing.
.
I often use Arduino sketches to test an AS7 Slave program.
You are more likely to get other readers to help with your project if it is easy to replicate on their hardware.
Admittedly this applies more to official Arduino targets. Tiny85 needs a third-party core with no official support.
.
Attach a Zip of your AS7 project with your Arduino test sketches.
Or a link to a GitHub project.
.
The first job in any I2C Slave project is to design its behaviour. e.g. report a Sensor, emulate a RTC, ...
.
David.

Last Edited: Tue. May 29, 2018 - 07:05 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Is there a tutorial somewhere for using Arduino TinyCore with Atmel Studio for development AND uploading via ISP (using a normal programmer, like a JTAGice mkII and non-exotic flash methods)?

 

At the moment, I'm kind of stuck between two seemingly-incompatible universes... I know how to develop stuff for bare-metal AVRs using Atmel Studio (or at least I did, and I'm relearning quickly how to do it now), and I know how to develop stuff for canonical Arduino boards using Arduino's (piss poor) IDE, but I'm struggling badly at bridging the two universes (specifically, using Arduino libraries with bare-metal AVRs from within Atmel Studio itself).

 

Examples of the problems I ran into on Sunday (when I first started to look at what it would take to use Arduino libraries on bare-metal AVRs):

 

* Atmel Studio can import an Arduino project... but apparently, only if it's for a board known independently to Atmel Studio. I added the TinyCore definitions to the Arduino IDE using board manager, created a new project, and got it to compile without errors... but when I tried importing that project into Atmel Studio as an Arduino project, it complained about it having an "invalid board".

 

* I have NEVER successfully gotten the Arduino IDE to even acknowledge the existence of my JTAGice mkII, let alone use it. I've gotten the distinct impression that even today, AVRdude and the JTAGice mkII aren't particularly fond of each other.

There's no place like ~/

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0
void setup() {
	DDRB |= (1<<3);
	PORTB &= ~(1<<3);
	PINB |= (1<<3);

	// as I understand C, the elements of USI_Slave_register_buffer are pointers to unsigned chars.
	// The code I have below should, theoretically, cause it to return 0xf0 when asked to read register 0, 0xca when asked to read register 1, and so on.
	unsigned char uno = 0xf0;
	USI_Slave_register_buffer[0] = (unsigned char*)&uno;
	unsigned char dos = 0xca;
	USI_Slave_register_buffer[1] = (unsigned char*)&dos;
	unsigned char tres = 0x69;
	USI_Slave_register_buffer[2] = (unsigned char*)&tres;
	unsigned char cuatro = 0x42;
	USI_Slave_register_buffer[3] = (unsigned char*)&cuatro;

This code looks "dangerous" at best and I don't see how it's going to work? You create these stack frame locals. They only persist as long as setup() is in context. On exit their stack space will be lost and the locations may then be used for other things but it's kind of too late as you have assigned the addresses of those locations to members of the USI_Slave_register_buffer[] array. So it now holds the addresses of four variables that no longer exist?

 

If you want to pass back the address of locals from a routine they MUST be "static" so they are allocated in BSS/.data

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 1

I can never understand why people are rude about the Arduino IDE.

I regularly swap between Uno, Zero, Due, STM32, ESP32, ESP8266, ...

 

I can build and test library code ( C++ ) with the IDE.    Ok,  I use Notepad+ to edit the C++.

But it is often handy to test some local library code in a sketch tab.    Everything done in the IDE.

 

I digress.    If you like AS7,   build Arduino in AS7.    But you still have to "export" it back to the Arduino IDE for final Release.

AS7 "import" is a bit flaky.    And "import" from a third party core is even more flaky.

 

I was suggesting regular TinyWireS sketches on t85 and regular Wire sketches on Uno.     Adapted from the TinyWireS and Wire examples and built with IDE.

 

Yes,   when it comes to any bare metal replacement of the TinyWireS Slave,   you will probably use C in AS7.

 

My main point has always been:   Design what you want your Slave to do first.    Get it working with the most convenient tools e.g. TinyWireS

 

David.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

david.prentice wrote:
you still have to "export" it back to the Arduino IDE for final Release

Why?

 

If you like AS, why can't it just stay there forevermore ?

Top Tips:

  1. How to properly post source code - see: https://www.avrfreaks.net/comment... - also how to properly include images/pictures
  2. "Garbage" characters on a serial terminal are (almost?) invariably due to wrong baud rate - see: https://learn.sparkfun.com/tutorials/serial-communication
  3. Wrong baud rate is usually due to not running at the speed you thought; check by blinking a LED to see if you get the speed you expected
  4. Difference between a crystal, and a crystal oscillatorhttps://www.avrfreaks.net/comment...
  5. When your question is resolved, mark the solution: https://www.avrfreaks.net/comment...
  6. Beginner's "Getting Started" tips: https://www.avrfreaks.net/comment...
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

If your final project is using Arduino libraries, you would want to maintain Arduino build-ability.
If your project is private it does not really matter.
.
I was speaking from my own experience. I maintain one set of library source code. It might be built with Arduino IDE, Keil, Rowley, AS7. Multiple source folders give you brain ache.
.
As with any software some code might change in a new library version or new compiler version.
We don't know what functionality the t25 Slave will have. It is unlikely to be very complex in a 2kB chip. I doubt if there is anything to worry about.
.
David.

Last Edited: Tue. May 29, 2018 - 05:33 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

In addition to software, 6.8K pull-up resistors seem pretty large, especially if the prototyping board is one of those "spring" boards. I would use something in the 1.5K to 1.0K range, maybe even a bit smaller, depending on the power supply voltage.

 

Jim

Jim Wagner Oregon Research Electronics, Consulting Div. Tangent, OR, USA http://www.orelectronics.net

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

OK, great news! The tiny25 end is now working (or at least, the enumeration program running on the Uno is seeing it now).

 

I found a different library and example app on Github to try ( https://github.com/mvadai/attiny... ). That itself didn't fix the problem, but after doing the following... it started to respond:

 

1. Changed resistors to 4.7k. It turns out, the resistors weren't 6.8k after all... they were 680 ohms (grrrr... I really need to improve the lighting at my computer desk so brown, red, and orange don't look practically alike without extra lighting and a magnifying glass...)

 

2. Physically unplugged the ISP header (SCK is the same pin as SCL, and MOSI is the same pin as SDA).

 

For what it's worth, the original code I posted is still broken, even with the new resistors and ISP header's removal... but that's ok, at least now I have something that seems to work now that I can use as a starting point.

 

The new, working Tiny25 Atmel Studio 7 project is attached for posterity in case some future person needs a working example of a Tiny25 I2C slave. The Arduino enumeration sketch is unchanged from the original post.

 

Wiring that works:

  • pin 2 -> LED cathode -> 1k resistor -> +5v
  • pin 7 -> 4.7k resistor -> +5v
  • pin 5 -> 4.7k resistor -> +5v
  • pin 4 to ground (and .1uF cap)
  • pin 8 to +5v (and other terminal of .1uF cap)
  • pin 7 (SCK) to SCK on Arduino Uno
  • pin 5 (MOSI) to MOSI on Arduino Uno
  • wire between Arduino's ground pin and Tiny25's ground pin

 

Attachment(s): 

There's no place like ~/