ATMEGA328pb as TWI Slave not responding

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

I am working on a project that uses several ATMega328pb MCU's ... Making a Remote controlled K-9 from Dr.Who 

_______________              ______________                ______________________

|      REMOTE        |             |     Receiver      |               |             HEAD                 |

|   ATMega328pb   |             |  ATMega328pb |     TWI    | ATtiny85 & Mega328pb    |

|      - NRF24l01+  | RF Link |   - NRF24l01+  |               | 2 PWM       2 pwmServos |

|                          |             |    -MCP23017   |               |                 Digital outputs|

|                          |             |                       |               |                 for dc motor    |

________________             ______________                ______________________

 

I have the Remote & the Receiver talking Via two NRF24l01+ units as a 4 byte burst.

I also have the Receiver (master) TWI talking to the MCP23017 that controls various LED's (random pattern)

And I have the Receiver (master) TWI talking to the ATTiny85 that is using PB3=PB4 as PWM outputs to control the Ears of K-9. (i did a separate controller to offload from the ATMEGA328pb that controls a lot.

 

I can NOT get the 'HEAD' ATMEGA328pb (slave) to respond to ANY request. I temporarily used sniffer script on the Receiver and output'd to Serial  and it saw both the MCP23017 and the ATtiny85 that was Slaved to 0x4C. 

I even tried to change the Slave address of the 'Head' ATMEGA328pb and still I get no response. I even tried to have a Pin go HIGH once the ISR(TWI0_vect) hit ... but it never went High. 

I have remarked out the ISR(TIMER0_COMA_vect) that I was using for PWM creation thinking too many Interrupts ... but still no joy.Also I only have LED's on the outputs for testing.

 

Any Help would be greatly appreciated.

 

Below is the program that I have right now.... including some testing bits that I was using to try and track down the issues.

 

Thank you

Michael

 

/*
 * K9-328PB-Tiny85-HEAD
 *
 * Created: 3/18/2018 9:38:29 AM
 *  Author: Michael Till
 */ 
/*
********************************************************************************
 						K-9 HEAD Controller ATMEGA328PB PART 
 	Created By Michael Till & Shea O'Connor
 	
 	Purpose is:
 	- I2c linked to Main Controller
	 - 1 Servo for Laser Barrel
	 - 1 Servo for Neck movement
	 - 1 Mosfet to gnd for Eye's light
	 - 1 Mosfet to gnd for Laser LED in barrel
	 - 2 Digital outputs for Sensor motor (antenna) control
	 
ATMEGA328p TQFP PIN OUT

1-PD3-				 9-PD5-	Spare		17-	SCLK			25-PC2
2-PD4-		 		10-PD6-Laser 		18-	AVCC			26-PC3-
3-PE0-				11-PD7-Eyes			19-PE2-Barrel PWM	27- SDA
4-	VCC				12-PB0 				20-	AREF			28- SCL
5-	GND				13-PB1-Sensor A		21- GND				29- /RST
6-PE1-spare PWM		14-PB2-Sensor B		22-PE3-NECK PWM		30- RXD0
7-	X-TAL			15-	MOSI			23-PC0				31- TXD0 
8-	X-TAL			16-	MISO			24-PC1				32- Int0 

******************* HEAD I2C Data Byte Structure  ****************
7	       6		 5		4		3		2		1		0
Laser LED			| Sensor |	 	|  NECK	| 		|	   Eyes
On		  OUT		IN	    OUT 	UP 		Down		    ON
/off	  /IN												/OFF
************************ MASKs ***********************************
HLB		  HLP	   HSI		HSO		HNU		HND		HB		HE

 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~	
 */
 #define F_CPU 16000000		// AVR Clock Freq
 #include <avr/io.h> 
 #include <stdio.h>
 #include <avr/interrupt.h>
 #include "delay.h"
 

// ***********    PINS DEFINE   *****
#define SOUTp		0b00000010	//PB			// Motor Dir PIN
#define SINp		0b00000100	//PB			// Motor Dir Pin
#define NECKpwm		0b00001000	//PE			// Neck Servo PWM pin
#define BARRELpwm	0b00000100	//PE			// Barrel PWM Pin
#define EYEp		0b10000000	//PD			// Eye Enable Pin
#define LASERp		0b01000000	//PD			// Laser Enable pin

// **********	MACROS	**************

#define		_BAUD			38400
#define		F_SCL 400000UL 			// SCL frequency
#define		Prescaler 1
#define		TWBR_val ((((F_CPU / F_SCL) / Prescaler) - 16 ) / 2)
#define 	I2C_READ 0x01
#define 	I2C_WRITE 0x00

#define CTC_MAX 	2560
#define CTC_min		64
#define Lin			0				// PWM value of Barrel IN
#define Lout		200				// PWM Value of Barrel OUT


// ***Head Macros***
#define HLB			0b10000000		// Laser Set Bit Mask
#define HLP			0b01000000		// Laser Position Bit Mask
#define HSI			0b00100000		// Head Sensor IN Bit Mask
#define HSO			0b00010000		// Head Sensor OUT Bit Mask
#define HNU			0b00001000		// Head Neck UP Bit Mask
#define HND			0b00000100		// Head Neck DOWN Bit Mask
#define HB			0b00000010		// blank
#define HE			0b00000001		// Head EYE LED on/off mask
#define LaserOut		215			// Laser Servo MAX CCW
#define LaserIn			45			// Laser Servo MIN CW
#define NeckUP			220			// Max value for Neck position
#define NeckDown		10			// Min Value for Neck Position

#define SensorOUT   PORTB |= (0b00000010)		// SOUTp HIGH
#define SensorIN	PORTB |= (0b00000100)		// SINp HIGH
#define SensorSTOP  PORTB &= (0b11111001)		// SOUTp & SINp LOW
#define EyeON		PORTD |= (0b10000000)		// Eyes ON
#define EyeOFF		PORTD &= (0b01111111)		// Eyes OFF
#define LaserON		PORTD |= (0b01000000)		// Laser ON
#define LaserOFF	PORTD &= (0b10111111)		// Laser OFF

// ####  I2C  ####
/* Slave Receiver */
#define TW_SR_SLA_ACK			0x60		// SLA+W received, ACK returned
#define TW_SR_ARB_LOST_SLA_ACK	0x68		// arbitration lost in SLA+RW, SLA+W received, ACK returned
#define TW_SR_GCALL_ACK			0x70		// general call received, ACK returned
#define TW_SR_ARB_LOST_GCALL_ACK 0x78		// arbitration lost in SLA+RW, general call received, ACK returned
#define TW_SR_DATA_ACK			0x80		// data received, ACK returned
#define TW_SR_DATA_NACK			0x88		// data received, NACK returned
#define TW_SR_GCALL_DATA_ACK	0x90		// general call data received, ACK returned
#define TW_SR_GCALL_DATA_NACK	0x98		// general call data received, NACK returned
#define TW_SR_STOP				0xA0		// stop or repeated start condition received while selected


#define			HEAD			0x16			// NOTE Slave address of 0x16 is shifted once to the right
												// Master sees it at 0x2c

// *******	  Variables     *******
uint8_t		Mode		= 0;					// Alert Mode 0-3
uint8_t		HeadIn		= 0;
uint8_t		New_Data	= 0;
uint16_t 	StepCount	= 0;				// Counts of 7.75us
uint16_t	NECK_Pos	= 0;				//  NECK  Position Value (0-255)
uint16_t	BARREL_Pos	= 0;				// Barrel Position Value (0-255) 
uint8_t		flash		= 0;

// *******    Functions		*******

/*ISR(TIMER0_COMPA_vect){
	if (StepCount < CTC_MAX)
	{	StepCount++;	}
	else
	{	StepCount = 0;
		PORTE |= (NECKpwm | BARRELpwm);
	}
	if (StepCount == (NECK_Pos+CTC_min)) {PORTE &= ~(NECKpwm);}
	if (StepCount == (BARREL_Pos+CTC_min)) {PORTE &= ~(BARRELpwm);}
}*/
ISR(TWI0_vect)
{
	if( (TWSR0 & 0xF8) == TW_SR_SLA_ACK ){
		TWCR0 |= (1<<TWIE) | (1<<TWINT) | (1<<TWEA) | (1<<TWEN);
	}
	else if( (TWSR0 & 0xF8) == TW_SR_DATA_ACK )
		HeadIn = TWDR0;
	New_Data = 1;
}
void initIO()
{	// Port B initialization
	// Function: PB7=Xtal PB6=Xtal PB5=Out(SCK) PB4=In(MISO)
		//		 PB3=Out(MOSI) PB2=Out(Sensor IN) PB1=Out(Sensor OUT) PB0=Out
	DDRB= 0b00101111;
/*	(0<<DDB7) |		// XTAL
	(0<<DDB6) |		// XTAL
	(1<<DDB5) |		// SCK
	(0<<DDB4) |		// MISO
	(1<<DDB3) |		// MOSI
	(1<<DDB2) |		//  Sensor IN motor 
	(1<<DDB1) |		//  Sensor Out Motor
	(1<<DDB0);		// Spare
	// State: Bit7=0 Bit6=0 Bit5=T Bit4=T Bit3=T Bit2=0 Bit1=0 Bit0=0
*/
	PORTB=(0<<PORTB7) | (0<<PORTB6) | (0<<PORTB5) | (0<<PORTB4) | (0<<PORTB3) | (0<<PORTB2) | (0<<PORTB1) | (0<<PORTB0);
	// NO PULL UPS
	//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
	// Port C initialization
	// Function: Bit6=In (RESET) Bit5=in (SCL Slave) Bit4=in (SDA Slave) Bit3=Out Bit2=Out Bit1=Out Bit0=Out
	DDRC= 0b000000111;
/*	(0<<DDC6) |	// RESET
	(0<<DDC5) |			// SCL 
	(0<<DDC4) |			// SDA
	(1<<DDC3) |			//		optional Stepper control
	(1<<DDC2) |			//		optional Stepper control
	(1<<DDC1) |			//		optional Stepper control
	(1<<DDC0);			//		optional Stepper control
	// State: Bit6=T Bit5=0 Bit4=0 Bit3=T Bit2=T Bit1=T Bit0=T
*/	
	PORTC=(0<<PORTC6) | (1<<PORTC5) | (1<<PORTC4) | (0<<PORTC3) | (0<<PORTC2) | (0<<PORTC1) | (0<<PORTC0);
	// NO PULL UPS
	//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
	// Port D initialization
// Function: Bit7=Out(Eyes) Bit6=Out(Laser) Bit5=Out(Spare) Bit4=Out Bit3=Out Bit2=In(int0) Bit1=Out(TX) Bit0=In(RX)
	DDRD= 0b11111010;
/*
	(1<<DDD7) |			//  Eyes On/Off Output 
	(1<<DDD6) |			//  Laser On/Off Output 
	(1<<DDD5) |			//  Spare
	(1<<DDD4) |			//  unused
	(1<<DDD3) |			//  unused
	(0<<DDD2) |			//	INT0 - unused
	(1<<DDD1) |			//	Serial TX
	(0<<DDD0);			//	Serial RX
	// State: Bit7=0 Bit6=0 Bit5=0 Bit4=T Bit3=T Bit2=T Bit1=0 Bit0=T
*/
	PORTD=(0<<PORTD7) | (0<<PORTD6) | (0<<PORTD5) | (0<<PORTD4) | (0<<PORTD3) | (0<<PORTD2) | (1<<PORTD1) | (0<<PORTD0);
		//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
	// Port E initialization
// Function: Bit7=N/A Bit6=N/A Bit5=N/A Bit4=N/A 
//			 Bit3=Out(NECK pwm) Bit2=Out(BARREL pwm) Bit1=Out(Spare PWM) Bit0=Out(spare)
	DDRE=0b00001111;
/*	(1<<DDRE3) |		//  PWM Neck Output
	(1<<DDRE2) |			//	PWM Barrel output
	(1<<DDRE1) |			//	PWM Spare
	(1<<DDRE0);				//	Spare
	// State: Bit7=0 Bit6=0 Bit5=0 Bit4=T Bit3=T Bit2=T Bit1=0 Bit0=T
*/
	PORTE= (0<<PORTE3) | (0<<PORTE2) | (0<<PORTE1) | (0<<PORTE0);
	
//****** 	Timer 0 setup for PWM ***************
	// Timer 0 Init for Clk/2 CTC mode Interrupt OCIE2A enabled
	TCCR0A = 0b00000010;		// Bit 1 = WGM01  (sets Waveform for CTC mode)
	TCCR0B = 0b00000001;		// Bit 0 = CS20  ( sets Clock Select to CLKio / 1 [No prescaling])
	OCR0A  = 0x07c;				// sets Count of Clk ticks until CTC
//	TIMSK0 = 0b00000011;		// sets OCIE0A(Match) Interrupt and TOIE(Overflow) Interrupt
	TIMSK0 = 0b00000000;
}
void I2C_init(uint8_t address){
	TWBR0 = TWBR_val;
	TWAR0 = address;
	// set the TWCR to enable address matching and enable TWI, clear TWINT, enable TWI interrupt
	TWCR0 = (1<<TWIE)|(1<<TWEA)|(1<<TWINT)|(1<<TWEN);
}
void startup(){
	EyeON;SensorOUT;LaserON;PORTE = 0b00001100;
	_delay_ms(50);
	EyeOFF;SensorSTOP;LaserOFF;PORTE = 0b00000000;
	_delay_ms(80);
	EyeON;SensorIN;LaserON;PORTE = 0b00000100;
	_delay_ms(30);
	EyeOFF;SensorSTOP;LaserOFF;PORTE = 0b00001000;
	_delay_ms(100);
	EyeON;SensorIN;LaserON;PORTE = 0b00000100;
	_delay_ms(10);
	EyeOFF;SensorOUT;LaserOFF;PORTE = 0b00001000;
	_delay_ms(150);
	EyeON;SensorSTOP;PORTE = 0x00;
	
//	TIMSK0 = 0b00000011;		 // Enables Interrupts for the timer
	_delay_ms(20);
	
	NECK_Pos = 100;
	BARREL_Pos = 240;
	
}

/*  *********************** USART TX & RX ******************
void USART_INIT(uint16_t baud){
	uint16_t myubrr = (F_CPU/16/baud-1);
	UBRR0H = (uint8_t)(myubrr>>8);
	UBRR0L = (uint8_t)myubrr;
	//	UCSR0B |= (0b0000100);
	
	UCSR0B = ((1<<RXEN0)|(1<<TXEN0)); 		// Enable RX & TX
	//	UCSR0C |= (0b00000110);
	UCSR0C = (3<<UCSZ00);					// Setup as 8-N-1
}
int USARTWriteChar(char ch, FILE *stream){//  ******* USART TX & RX *************
	if (ch == '\n') USARTWriteChar('\r', stream);
	while (!(UCSR0A & (1<<UDRE0)) );		// waits for tx to finish
	UDR0 = ch;
	return 0;
}
int USARTReadChar(FILE *stream){
	char ch;
	while (!(UCSR0A & (1<<RXC0)));		// Ready to Read
	ch = UDR0;
	// uart_putch(ch, stream);			// echo back to TX
	return ch;
}
FILE uart_str = FDEV_SETUP_STREAM(USARTWriteChar, USARTReadChar, _FDEV_SETUP_RW);
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */

//  ************* USART INIT WORKS  ***************
void USART_INIT(uint16_t baud){
	uint16_t myubrr = (F_CPU/16/baud-1);
	UBRR0H = (uint8_t)(myubrr>>8);
	UBRR0L = (uint8_t)myubrr;
	//	UCSR0B |= (0b0000100);
	
	UCSR0B = ((1<<RXEN0)|(1<<TXEN0)); 		// Enable RX & TX
	//	UCSR0C |= (0b00000110);
	UCSR0C = (3<<UCSZ00);					// Setup as 8-N-1
}
int USARTWriteChar(char ch, FILE *stream){//  ******* USART TX & RX *************
	if (ch == '\n') USARTWriteChar('\r', stream);
	while (!(UCSR0A & (1<<UDRE0)) );		// waits for tx to finish
	UDR0 = ch;
	return 0;
}
int USARTReadChar(FILE *stream){
	char ch;
	while (!(UCSR0A & (1<<RXC0)));		// Ready to Read
	ch = UDR0;
	// uart_putch(ch, stream);			// echo back to TX
	return ch;
}
FILE uart_str = FDEV_SETUP_STREAM(USARTWriteChar, USARTReadChar, _FDEV_SETUP_RW);

int main(void)
{
	sei();	
	initIO();						// Call Init IO PORTS
	USART_INIT(_BAUD);				// Call Init USART
	stdout = stdin = &uart_str;
	I2C_init(HEAD);
	printf("Boot complete\n");
	
	printf(" TWSR0 = 0B");
	if (TWSR0 & 0x80) {printf("1");}else {printf("0");}
	if (TWSR0 & 0x40) {printf("1");}else {printf("0");}
	if (TWSR0 & 0x20) {printf("1");}else {printf("0");}
	if (TWSR0 & 0x10) {printf("1");}else {printf("0");}
	if (TWSR0 & 0x08) {printf("1");}else {printf("0");}
	if (TWSR0 & 0x04) {printf("1");}else {printf("0");}
	if (TWSR0 & 0x02) {printf("1");}else {printf("0");}
	if (TWSR0 & 0x01) {printf("1\n");}else {printf("0\n");}
	
	printf(" TWCR0 = 0B");
	if (TWCR0 & 0x80) {printf("1");}else {printf("0");}
	if (TWCR0 & 0x40) {printf("1");}else {printf("0");}
	if (TWCR0 & 0x20) {printf("1");}else {printf("0");}
	if (TWCR0 & 0x10) {printf("1");}else {printf("0");}
	if (TWCR0 & 0x08) {printf("1");}else {printf("0");}
	if (TWCR0 & 0x04) {printf("1");}else {printf("0");}
	if (TWCR0 & 0x02) {printf("1");}else {printf("0");}
	if (TWCR0 & 0x01) {printf("1\n");}else {printf("0\n");}
	
	printf(" TWAR0 = %#x\n",TWAR0);
	
	
    while(1)
    {	if (New_Data == 1) 
		{	if ((HeadIn & HLB) == HLB){					// On/OFF of the laser
				}
			 else {LaserOFF;
				}
			if ((HeadIn & HE) == HE) {					// On/OFF of the Eyes
				EyeON; 
				}
			else {EyeOFF; }
			if ((HeadIn & HSI) == HSI || ((HeadIn & HSO) == HSO)) {				// Move Sensor 
				if ((HeadIn & HSI) == HSI) {SensorIN ;}
				if ((HeadIn & HSO) == HSO) {SensorOUT;}
			else {SensorSTOP;}
			if ((HeadIn & HNU) == HNU) {NECK_Pos -= 1;	// Move Neck servo Up
				}
			if ((HeadIn & HND) == HND) {NECK_Pos += 1;	// Move Neck servo Down
				}
			if ((HeadIn & HLP) == HLP) {				// Laser position	
				BARREL_Pos = Lout; } 
			else {BARREL_Pos = Lin; } 
			
		  
			HeadIn = 1;
			New_Data = 0;
		}
		// ************* Heart Beat ***************
		if (flash == 0) 
		{	flash = 0x01;}
		else {flash = 0;}
		PORTE = flash;
		_delay_ms(50);
	// ************  Heart Beat End ***************			 
    }
}

 

This topic has a solution.
Last Edited: Sun. Mar 25, 2018 - 01:35 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I see :

void I2C_init(uint8_t address){
	TWBR0 = TWBR_val;
	TWAR0 = address;
	// set the TWCR to enable address matching and enable TWI, clear TWINT, enable TWI interrupt
	TWCR0 = (1<<TWIE)|(1<<TWEA)|(1<<TWINT)|(1<<TWEN);
}

but no ISR() or other twi functions???

Don't enable the interrupt with out one!

Jim

 

Mission: Improving the readiness of hams world wide : flinthillsradioinc.com

Interests: Ham Radio, Solar power, futures & currency trading - whats yours?

 

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

it's there just under functions after the Rem'ed out ISR for the timer

but here it is again.

 

Also Im only sending a single 8 bit word,  in the description area I have the byte structure.

ISR(TWI0_vect)
{
	if( (TWSR0 & 0xF8) == TW_SR_SLA_ACK ){
		TWCR0 |= (1<<TWIE) | (1<<TWINT) | (1<<TWEA) | (1<<TWEN);
	}
	else if( (TWSR0 & 0xF8) == TW_SR_DATA_ACK )
		HeadIn = TWDR0;
	New_Data = 1;
}

-Michael

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

I see it now, have you looked at your scl/sda lines with a scope?

Can you test at a lower speed(50k), what value pull up resistors are you using and vcc level?

I'm guessing you are using similar code in the other units that work, so looking for h/w issues.

What is the distance from head to master?

Ribbon cable or twisted pair?

 

Jim

 

Mission: Improving the readiness of hams world wide : flinthillsradioinc.com

Interests: Ham Radio, Solar power, futures & currency trading - whats yours?

 

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

I have not looked at the TWI line with a scope but I did use my Saleae analyzer ... and it wasd able to decode the traffic and confirmed I was addressing the Head ATMEGA328pb. BUT it was only sending  ... no ACK from slave all sends to that unit was NACK

I have a 4.7K pullup on both SDA and SCL. and I tried to talk to the Mega328pb slave with the others on the bus and then without any other devices on bus.

 

Well I have to use a different code for the ATTINY85 that is slave .. but that seems to work just fine.

they are on two protoboards right now . about 5 inchs apart... I have the Tiny85 and the 'Head' ATMEGA328pb on the same protoboard, ATTINY85 works fine.

I am using individual chips soldered on QFP-32 to DIP adapters... I have checked the solder connections and made sure there are no shorts.

 

I have also change the last bit of code  ""heartbeat" to each of the PC4 and PC5 outputs (disabling the TWI) and I did get the heartbeat on both pins separately.

 

Even though I don't want to do this ... im thinking my next step is to swap the two ATMEGA328pb and re Upload the programs and try it again ...

 

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

Since you are only receiving one byte from the MASTER, maybe you should do NACK after receiving that one byte from the MASTER.  Maybe  the master asserts SDA after the received ACK of the one data byte was sent. If the slave sent ACK then it is indicating that the slave expects to receive additional data.    By doing NACK instead of ACK, the Slave is releasing the SDA line.  The STOP condition occurs when the Master releases the SCL.

 

Why are you using interrupts on the TWI section?  They are infernally complicated for TWI.  Maybe it would be better to just wait 25 microseconds for the

TWI command to complete.

Last Edited: Wed. Mar 21, 2018 - 09:52 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Simonetta,

 

The NACK that i am reading is the Address of the Slave ATMEGA328pb.  the Master will actually send two '1' byte s through the TWI. 

first it sends the Slave address, as I under stand what I have read is that the Slave then Drops the SDA low to acknowledge the reception

... then releases it for the next Byte which is the DATA that is then put in to the TWDR registry. 'TWDR0' in the ATMEGA328pb.

 

Im using the Interrupt to let me know when I have received NEW data and to update the actions of the outputs.

as I read the Datasheet, the TWI and Interrupt operations is as follows :

Reception of transmission on the TWI bus  --- (TWI_vect) hits.

if( (TWSR0 & 0xF8) == TW_SR_SLA_ACK ){
		TWCR0 |= (1<<TWIE) | (1<<TWINT) | (1<<TWEA) | (1<<TWEN);

This verifies if the Received byte is the same as what is stored in the TWAR (Slave address) registry and ACK sent

else if( (TWSR0 & 0xF8) == TW_SR_DATA_ACK )

and this verifies that the next byte has sent an ACK at completion.

 

The next thing just move the DATA in the TWDR registry to the Global variable, and then I have a Flag setting for update check.

 

--Michael

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

UPDATE

 

I swapped the two ATMEGA328pb (main & head) reprogrammed and the problem persists ... same issue ... and same symptoms .

 

-Michael

 

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

I don't have much experience with the new pb, so since you have swapped out the h/w and assuming the soldering is ok, time to look again at the code.

AVRs have a fixed interrupt priority, so could there be another IRQ that is starving the TWI IRQ and preventing it from working as expected? (servo code/timer/external irq perhaps)

Try disabling sections of code to test this...  leaving only the TWI with LED status.

Any chance you have a debugger?

The PB has two TWI h/w, are you sure you have the correct signals connected to the expected TWI?  i.e. using TWI0 but signals connected to TWI1!?!

 

Jim

 

edit: add one more thought

Mission: Improving the readiness of hams world wide : flinthillsradioinc.com

Interests: Ham Radio, Solar power, futures & currency trading - whats yours?

 

Last Edited: Thu. Mar 22, 2018 - 01:21 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Jim,

 

I have done these tests already, 

I have disabled the ISR(TIMR0_COMPA_vect) and I have not activated any other Interrupts either Internal or External. 

I still have the Timer0 setup but changed my TIMSK to 0b00000000 or 0x00 so those Interrupts are not enabled.

 

The only Interrupt that I am requesting is the TWI ... using TWCR= 0b11000101 .. 

That is setting a 1 Bit to :

TWINT - TWI Interupt Flag (according to the Data sheet I have to write a 1 to clear the flag)

TWEA - TWI Enable Acknowledge (Generates ACK pulse )

TWEN - TWI Enabled

TWIE - TWI Interrupt Enable 

 

All other ports are raw digital (even PBE3 and PB2 are PWM generated with Timer0 Interupt But are disabled for testing.)

 

 

What could I be missing ...

 

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

I have even swapped ATMEGA328pb 's between the Receiver(master) and Head(Slave) ones, Reprogrammed and the same thing is happening.

 

Michael

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0
#define TW_SR_SLA_ACK			0x60		// SLA+W received, ACK returned

This means that the slave will wait for the master to send the correct slave address and the write bit-signal activated.  When that happens (and the TWI is configured correctly), the ISR will read 0x60 in the TWI status register (masking out the low three bits).  The ISR now configures the TWI to receive the byte that the master is going to send next (the master sent the Slave address with the bit0 low, meaning that the next TWI transfer is a write from the master to the slave).  The slave will assert an ACK following the reading of this next byte from the master.

  When the second TWI transfer finishes, the ISR will trigger again. This time it sees

if( (TWSR0 & 0xF8) == TW_SR_DATA_ACK )
		HeadIn = TWDR0;

    The two commands : HeadIn=TWDR0;  and  New_Data = 1;  should both be inside a brace-pair for the if statement.  Otherwise New_Data gets assigned a non-zero value after the master has only sent the slave address + W byte.    As that happens, the slave thinks that there is new valid data in HeadIn variable, but that variable actually contains value zero because HeadIn is not updated until after the second TWI interrupt.

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

 

Simonetta,

 

I thank you for explanation and suggestion. I will make those changes that you recommend.

 

But I don't think the ISR(TWI_vect) is even getting called. I added a visual test and your recommendation of brackets, see below;

ISR(TWI0_vect)
{ PORTE |= 0x08; 
	if( (TWSR0 & 0xF8) == TW_SR_SLA_ACK ){
		TWCR0 |= (1<<TWIE) | (1<<TWINT) | (1<<TWEA) | (1<<TWEN);
	}
	else if( (TWSR0 & 0xF8) == TW_SR_DATA_ACK )
	{HeadIn = TWDR0;
	New_Data = 1;}
}

On PE3 I have an LED , I added a small little test even for the LED to make sure it is wired right, and it lights in a startup call that tests the LED's.  and I am trying a sniffer routine from the Master on the TWI bus, and I never get a response on the Sniffer or the LED on PE3 .

 

So it appears that it is not even getting the TWI slave setup right.

 

I have the program outputing Via Serial , the TWI regs just before the While(1) in main ... and the out put is this:

 TWSR0 = 0B11111000                                                             
 TWCR0 = 0B01000101                                                             
 TWAR0 = 0x50 

Iv'e changed the Address around ... but still no luck.. the Sniffer on the master sees all the other devices just fine.  Is there a special sequence that needs to be followed? 

 

Im about ready to start to redesign the circuit with different chips ...  .. this is just strange. maybe the 328pb just does not like Slave ... or maybe shift it to TWI1 and off TWI0... i don't know...

 

-Thank you for helping me look into this... 

Michael

 

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

ettill777 wrote:
and I never get a response on the Sniffer or the LED on PE3 .

Granted, something does not seem right h/w wise, a scope would be a better tool here then a LA.

Two things to try,

1) lower speed from 400k down to 50k and see if the slave responds

2) use scope to look at bus levels at slow and high speeds.

What value of pull up resistors are you using and VCC level?

3) have you verified cpu speed of 328pb!

 

Jim

edit: add #3

Mission: Improving the readiness of hams world wide : flinthillsradioinc.com

Interests: Ham Radio, Solar power, futures & currency trading - whats yours?

 

Last Edited: Fri. Mar 23, 2018 - 01:26 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Jim,

 

I don't think it is hardware.. only because I have tow ATMEGA328PB, one as the master , other as slave, I have swapped them and reprogrammed and the TWI works as master on both physical chips.

 

1: I have lowered the speed to 100k with no change. 

2: I will try to break out my O-scope this weekend, but it does not have storage. ...   I have a total of three slave devices; MCP23017, ATTINY85, and ATMEGA328pb.  both MCP23017 & ATTINY85 works. I have even removed both and directly wired just the two ATMEGA328pb only and still same issue. 

3: I am using a 4.7K resistors from VCC (+5Vdc) to SDA and SCL on the Master only. 

4: Im fairly sure the CPU speed is correct due to the Baud rate is called for 38400 on both Master and Slave serial ports, for debugging, and they both read true via Realterm. Im using the same baud call and Define for calculation on both. 

   All clock Fuses and hardware is Identical for the Caps and X-tal. 

 

This reply has been marked as the solution. 
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I can close this one down....

 

It was my own stupidity. I started to disassemble it to shit to TWI1 and test .... and found a bad wire under my 32QFN adapter board on the SCL line... 

 

I'm sorry for wasting anyone's time.

 

Michael

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

Thank you for posting the explanation, because that means that when someone else gets a similar thing, they might solve it faster.

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

So it WAS as h/w issue!   Thanks for the update!

 

Jim

 

Mission: Improving the readiness of hams world wide : flinthillsradioinc.com

Interests: Ham Radio, Solar power, futures & currency trading - whats yours?

 

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

I also Wish to add something...

 

I was having some issues that randomly it would seem to loose the 16mhz clock .

My "heartbeat" LED that would strobe about 4 times a second would randomly (sometimes when IRQ 0 would hit) would change to a rate of 1 flash every 2-3 seconds... 

Resting the MCU would not fix it ... I would have to remove power completely to restore the 16Mhz clock.

And I had a 16Mhz xtal on PB6 & PB7. with 22pf Caps to ground.  I also tried to change it to 10pF caps. still same thing ...

I am using the Adafruit 32 TQFP bearkout board. 

https://www.adafruit.com/product...

The ONLY fix I was able to come up with was using a actual 16Mhz TTL Clock input on PB6 and that fixed everything. 

It seems that the Xtal Amplifier is alittle weak on the 328pb... 

Dont know if it is with the breakout board... or if is a issue with the 328pb. 

 

SO ... if anyone is having issues with Frequency instability using atmega328pb on a Breakoutboard Try using something like this:

CTS-Frequency Controls CB3-3C-16M0000

https://www.digikey.com/product-...

 

Thought I would Share.

Michael