Forum: Mikrocontroller und Digitale Elektronik I2C meldet status 0x38


von Sven Müller (Gast)


Lesenswert?

Hallo Leute,

ich habe einen Atmega 644PA,
und den BLMC von Ulrich Radig.

Der Atmega644 sendet 2Bytes und danach meldet der TWI 0x38, also 
Arbitration lost in SLA+W or data bytes. Hat jemand ne Ahnung wie das 
kommt?

Danke im Voraus.

von holger (Gast)


Lesenswert?

>Der Atmega644 sendet 2Bytes und danach meldet der TWI 0x38, also
>Arbitration lost in SLA+W or data bytes. Hat jemand ne Ahnung wie das
>kommt?

Da zieht irgendwer an den I2C Leitungen.
Clockstretching vom BLMC? Keine Ahnung wie der arbeitet.

von Ulrich Radig (Gast)


Lesenswert?

Hallo,

Pullup Widerstand an SDA und SCL?

Gruß
Uli

von Sven Müller (Gast)


Lesenswert?

Hallo ihr beiden,

was meinst du mit Clockstretching.

Ja SDA und SCL haben 10kOhm

Gruß Sven

von holger (Gast)


Lesenswert?

>was meinst du mit Clockstretching.

Ein uC I2C Slave ist häufig zu langsam um sofort zu antworten.
Um sich ein bisschen Zeit zu verschaffen zieht er einfach
die Clockleitung runter. Wenn er bereit ist lässt er sie wieder los.
Das sollte der I2C Master abkönnen.

Was genau bei dir abgeht solltest du mal mit einem Logicanalyzer
oder Speicherosci ansehen. So ist das nur willenloses rumgerate.

Dein Programm in einer Minimalform zeigen wo der Fehler auftritt
könnte auch ungemein hilfreich sein.

von Sven Müller (Gast)


Lesenswert?

Da wo "hier" steht bleibt er beim nächsten Senden stecken
und das printf liefert vorher halt 0x38. Zwischen jedem Senden wird 
1Sek.
gewartet.
1
uint8_t TWIM_Write (uint8_t byte)
2
  {
3
  uint8_t   twst;
4
/*
5
** Send data to the previously addressed device
6
*/
7
  TWDR = byte;
8
  TWCR = (1<<TWINT)|(1<<TWEN);
9
/*
10
** Wait until transmission completed
11
*/
12
  while (!(TWCR & (1<<TWINT)));/*hier*/
13
/*
14
** Check value of TWI Status Register. Mask prescaler bits
15
*/
16
  twst = TWSR & 0xF8;
17
  printf("0x%02x\n",twst);
18
  if (twst != TWI_MTX_DATA_ACK) return 1;
19
20
  return 0;
21
  }

von holger (Gast)


Lesenswert?

Wie wäre es mit einem vollständigen Programm?
Möglicherweise gibt dir der BLMC kein ACK weil die
I2C Adresse schon falsch gesendet wurde.

von Ulrich Radig (Gast)


Lesenswert?

oder kein I2C Start

von Wilhelm F. (Gast)


Lesenswert?

Immerhin gibt es den Status 0x38, und bestimmt auch einen Grund und eine 
Beschreibung dazu.

von Sven Müller (Gast)


Lesenswert?

Unten habe ich mal die main.c und die TWI_Master.c

main.c
1
/*******************************************************
2
 Author:          Manfred Langemann
3
 mailto:          Manfred.Langemann ät t-online.de
4
 Begin of project:      04.01.2008
5
 Latest version generated:  04.01.2008
6
 Filename:          Main.c
7
 Description:          Main routine for testing
8
               TWI_Master_main.c
9
 ********************************************************/
10
#include <stdio.h>
11
#include <avr/interrupt.h>
12
13
#include "General.h"
14
#include "RS232.h"
15
#include "Delay.h"
16
#include "TWI_Master.h"
17
/*
18
** This main programm demonstrates how to use the 
19
** implemented TWI master functions. These are:
20
**  TWIM_Init
21
**  TWIM_ReadAck
22
**  TWIM_ReadNack
23
**  TWIM_Write
24
**  TWIM_Stop
25
**
26
** For testing this program, use the program
27
** TWI_Slave_main.c in the slave uC and connect the
28
** two TWI lines properly (don't forget to also
29
** connect GND between Master and Slave!)
30
**
31
** Used uC for Master is ATMega32
32
*/
33
int main (void)
34
  {
35
  uint8_t    i;
36
  uint8_t    j=0;
37
  //uint8_t    Data[8];
38
  uint8_t    SlaveAddress = 0;
39
/*
40
** Clear any interrupt
41
*/
42
  cli ();
43
/*
44
** Wait 1 second for POR
45
*/
46
  Delay_ms (1000);
47
/*
48
** Initiate RS232
49
*/
50
  RS232_Init ();
51
  printf ("Hello world...\n");
52
/*
53
** Initiate TWI Master Interface with bitrate of 100000 Hz
54
*/
55
  if (!TWIM_Init (100000))
56
    {
57
    printf ("Error in initiating TWI interface\n");
58
    while (1);
59
    }
60
/*
61
** Endless loop
62
*/
63
  while (1)
64
    {
65
/*
66
** Write byte(s) to the slave.
67
** It is implicitely assumed, that the slave will
68
** accepts 8 bytes
69
*/
70
      if (!TWIM_Start (SlaveAddress, TWIM_WRITE))
71
      {
72
      TWIM_Stop ();
73
      printf ("Could not start TWI Bus for WRITE\n");
74
        }
75
    else
76
      {
77
            TWIM_Write (j++);
78
        printf ("Byte sent: %d\n", j);
79
      TWIM_Stop ();
80
      Delay_ms (1000);
81
      }
82
    }
83
84
  return 0;
85
  }
TWI-Master
1
#include <stdio.h>
2
#include <avr/interrupt.h>
3
4
#include "General.h"
5
#include "TWI_Master.h"
6
7
/****************************************************************************
8
  TWI State codes
9
****************************************************************************/
10
// General TWI Master staus codes                      
11
#define TWI_START          0x08  // START has been transmitted  
12
#define TWI_REP_START        0x10  // Repeated START has been transmitted
13
#define TWI_ARB_LOST        0x38  // Arbitration lost
14
15
// TWI Master Transmitter staus codes                      
16
#define TWI_MTX_ADR_ACK        0x18  // SLA+W has been tramsmitted and ACK received
17
#define TWI_MTX_ADR_NACK      0x20  // SLA+W has been tramsmitted and NACK received 
18
#define TWI_MTX_DATA_ACK      0x28  // Data byte has been tramsmitted and ACK received
19
#define TWI_MTX_DATA_NACK      0x30  // Data byte has been tramsmitted and NACK received 
20
21
// TWI Master Receiver staus codes  
22
#define TWI_MRX_ADR_ACK        0x40  // SLA+R has been tramsmitted and ACK received
23
#define TWI_MRX_ADR_NACK      0x48  // SLA+R has been tramsmitted and NACK received
24
#define TWI_MRX_DATA_ACK      0x50  // Data byte has been received and ACK tramsmitted
25
#define TWI_MRX_DATA_NACK      0x58  // Data byte has been received and NACK tramsmitted
26
27
// TWI Slave Transmitter staus codes
28
#define TWI_STX_ADR_ACK        0xA8  // Own SLA+R has been received; ACK has been returned
29
#define TWI_STX_ADR_ACK_M_ARB_LOST  0xB0  // Arbitration lost in SLA+R/W as Master; own SLA+R has been received; ACK has been returned
30
#define TWI_STX_DATA_ACK      0xB8  // Data byte in TWDR has been transmitted; ACK has been received
31
#define TWI_STX_DATA_NACK      0xC0  // Data byte in TWDR has been transmitted; NOT ACK has been received
32
#define TWI_STX_DATA_ACK_LAST_BYTE  0xC8  // Last data byte in TWDR has been transmitted (TWEA = “0”); ACK has been received
33
34
// TWI Slave Receiver staus codes
35
#define TWI_SRX_ADR_ACK        0x60  // Own SLA+W has been received ACK has been returned
36
#define TWI_SRX_ADR_ACK_M_ARB_LOST  0x68  // Arbitration lost in SLA+R/W as Master; own SLA+W has been received; ACK has been returned
37
#define TWI_SRX_GEN_ACK        0x70  // General call address has been received; ACK has been returned
38
#define TWI_SRX_GEN_ACK_M_ARB_LOST  0x78  // Arbitration lost in SLA+R/W as Master; General call address has been received; ACK has been returned
39
#define TWI_SRX_ADR_DATA_ACK    0x80  // Previously addressed with own SLA+W; data has been received; ACK has been returned
40
#define TWI_SRX_ADR_DATA_NACK    0x88  // Previously addressed with own SLA+W; data has been received; NOT ACK has been returned
41
#define TWI_SRX_GEN_DATA_ACK    0x90  // Previously addressed with general call; data has been received; ACK has been returned
42
#define TWI_SRX_GEN_DATA_NACK    0x98  // Previously addressed with general call; data has been received; NOT ACK has been returned
43
#define TWI_SRX_STOP_RESTART    0xA0  // A STOP condition or repeated START condition has been received while still addressed as Slave
44
45
// TWI Miscellaneous status codes
46
#define TWI_NO_STATE        0xF8  // No relevant state information available; TWINT = “0”
47
#define TWI_BUS_ERROR        0x00  // Bus error due to an illegal START or STOP condition
48
49
/*******************************************************
50
 Public Function: TWIM_Init
51
52
 Purpose: Initialise the TWI Master Interface
53
54
 Input Parameter:
55
   - uint16_t  TWI_Bitrate (Hz)
56
57
 Return Value: uint8_t
58
   - FALSE:  Bitrate too high
59
   - TRUE:    Bitrate OK
60
61
*******************************************************/
62
uint8_t TWIM_Init (uint32_t TWI_Bitrate)
63
  {
64
/*
65
** Set TWI bitrate
66
** If bitrate is too high, then error return
67
*/
68
  TWBR = ((F_CPU/TWI_Bitrate)-16)/2;
69
  if (TWBR < 11) return FALSE;
70
71
  return TRUE;
72
  }
73
/*******************************************************
74
 Public Function: TWIM_Start
75
76
 Purpose: Start the TWI Master Interface
77
78
 Input Parameter:
79
   - uint8_t  Device address
80
   - uint8_t  Type of required Operation:
81
        TWIM_READ: Read data from the slave
82
        TWIM_WRITE: Write data to the slave
83
84
 Return Value: uint8_t
85
    - TRUE:    OK, TWI Master accessible
86
   - FALSE:  Error in starting TWI Master
87
88
*******************************************************/
89
uint8_t TWIM_Start (uint8_t Address, uint8_t TWIM_Type)
90
  {
91
  uint8_t    twst;
92
/*
93
** Send START condition
94
*/
95
  TWCR = (1<<TWINT)|(1<<TWSTA)|(1<<TWEN);
96
/*
97
** Wait until transmission completed
98
*/
99
  while (!(TWCR & (1<<TWINT)));
100
/*
101
** Check value of TWI Status Register. Mask prescaler bits.
102
*/
103
  twst = TWSR & 0xF8;
104
  printf("0x%02x\n",twst);
105
  if ((twst != TWI_START) && (twst != TWI_REP_START)) return FALSE;
106
/*
107
** Send device address
108
*/
109
  TWDR = (Address<<1) + TWIM_Type;
110
  TWCR = (1<<TWINT)|(1<<TWEN);
111
/*
112
** Wait until transmission completed and ACK/NACK has been received
113
*/
114
  while (!(TWCR & (1<<TWINT)));
115
/*
116
** Check value of TWI Status Register. Mask prescaler bits.
117
*/
118
  twst = TWSR & 0xF8;
119
  printf("0x%02x\n",twst);
120
  if ((twst != TWI_MTX_ADR_ACK) && (twst != TWI_MRX_ADR_ACK)) return FALSE;
121
122
  return TRUE;
123
  }
124
/*******************************************************
125
 Public Function: TWIM_Stop
126
127
 Purpose: Stop the TWI Master
128
129
 Input Parameter: None
130
131
 Return Value: None
132
133
*******************************************************/
134
void TWIM_Stop (void)
135
  {
136
/*
137
** Send stop condition
138
*/
139
  TWCR = (1<<TWINT)|(1<<TWEN)|(1<<TWSTO);
140
/*
141
** Wait until stop condition is executed and bus released
142
*/
143
  while (TWCR & (1<<TWINT));
144
  }
145
/*******************************************************
146
 Public Function: TWIM_Write
147
148
 Purpose: Write a byte to the slave
149
150
 Input Parameter:
151
   - uint8_t  Byte to be sent
152
153
 Return Value: uint8_t
154
    - TRUE:    OK, Byte sent
155
   - FALSE:  Error in byte transmission
156
157
*******************************************************/
158
uint8_t TWIM_Write (uint8_t byte)
159
  {
160
  uint8_t   twst;
161
/*
162
** Send data to the previously addressed device
163
*/
164
  TWDR = byte;
165
  TWCR = (1<<TWINT)|(1<<TWEN);
166
/*
167
** Wait until transmission completed
168
*/
169
  while (!(TWCR & (1<<TWINT)));
170
/*
171
** Check value of TWI Status Register. Mask prescaler bits
172
*/
173
  twst = TWSR & 0xF8;
174
  printf("0x%02x\n",twst);
175
  if (twst != TWI_MTX_DATA_ACK) return 1;
176
177
  return 0;
178
  }
179
/*******************************************************
180
 Public Function: TWIM_ReadAck
181
182
 Purpose: Read a byte from the slave and request next byte
183
184
 Input Parameter: None
185
186
 Return Value: uint8_t
187
    - uint8_t  Read byte
188
189
*******************************************************/
190
uint8_t TWIM_ReadAck (void)
191
  {
192
  TWCR = (1<<TWINT)|(1<<TWEN)|(1<<TWEA);
193
  while (!(TWCR & (1<<TWINT)));    
194
195
  return TWDR;
196
  }
197
/*******************************************************
198
 Public Function: TWIM_ReadAck
199
200
 Purpose: Read the last byte from the slave
201
202
 Input Parameter: None
203
204
 Return Value: uint8_t
205
    - uint8_t  Read byte
206
207
*******************************************************/
208
uint8_t TWIM_ReadNack (void)
209
  {
210
  TWCR = (1<<TWINT)|(1<<TWEN);
211
  while(!(TWCR & (1<<TWINT)));
212
  
213
  return TWDR;
214
  }

von Sven Müller (Gast)


Lesenswert?

Ulrich Radig schrieb:
> oder kein I2C Start

Wird einwandfrei ausgeführt

von Ulrich Radig (Gast)


Lesenswert?

auch schon mal eine andere Slaveadresse probiert?

von holger (Gast)


Lesenswert?

>auch schon mal eine andere Slaveadresse probiert?

>  uint8_t    SlaveAddress = 0;

0 ist sicher nicht richtig;)

von Sven Müller (Gast)


Lesenswert?

Wenn ich versuche die adresse 0x0C zu nehmen bekomme ich "Could not 
start TWI Bus for WRITE". Also bleibe ich schon beim Starten hängen.

Hat der Atmega88 vom BLMC vllt. nen CKDIV8 oder etwas ähnliches was den 
Takt ändert?

Oder gibt es noch etwas was ich bei den Fuse-Bits ändern muss außer 
Externer Quarz also... Full swing crystal oscillator?

von Sven Müller (Gast)


Lesenswert?

holger schrieb:
> 0 ist sicher nicht richtig;)

0 spricht alle I2C-Teilnehmer an.

von holger (Gast)


Lesenswert?

>holger schrieb:
>> 0 ist sicher nicht richtig;)
>
>0 spricht alle I2C-Teilnehmer an.

Du willst aber nur einen. Wenn 0x0C nicht geht versuch 0x06.

von holger (Gast)


Lesenswert?

Aus Ulrichs Code

#define MOTOR_ADR 0x70

von Sven Müller (Gast)


Lesenswert?

holger schrieb:
> Du willst aber nur einen.

Im Grunde ist erstmal egal ob nur Einer oder Mehrere.

Auch 0x06 bringt kein start erfolg.

von Ulrich Radig (Gast)


Lesenswert?

Welche adressen wurden vergeben?

von holger (Gast)


Lesenswert?

>> Du willst aber nur einen.
>
>Im Grunde ist erstmal egal ob nur Einer oder Mehrere.

Nein, ist es nicht.

>Welche adressen wurden vergeben?

Das ist vermutlich das Problem.

von I2C Neuling (Gast)


Lesenswert?

Sven Müller schrieb:
> 0 spricht alle I2C-Teilnehmer an.
Da gibt es einen broad cast?
Weiss jemand mal ne gute Beschreibung über das I2C Protokoll?

von Ulrich Radig (Gast)


Lesenswert?

So sehe ich das auch. Jeder Slave im Bus braucht eine eigene Adresse 
(gerade Adresse).

von Sven Müller (Gast)


Lesenswert?

In der BLMC Software ist 0x0C eingestellt und auf die adresse 0 
antwortet er ja 2mal mit einem ACK und danach nicht mehr.

von Sven Müller (Gast)


Lesenswert?

I2C Neuling schrieb:
> Da gibt es einen broad cast?

Ja der I2C hat einen broadcast.

@Ulrich Radig
Hast du Zeit das wir vllt. mal miteinander Sprechen können?

von holger (Gast)


Lesenswert?

>In der BLMC Software ist 0x0C eingestellt und auf die adresse 0
>antwortet er ja 2mal mit einem ACK und danach nicht mehr.

Auf die antwortet er aber nicht. Auf die um 1 Bit nach rechts geschobene
Adresse auch nicht. Dein Programm schiebt die Adresse ja um eine Stelle
nach links.

Hast du das Programm mit der neuen Adresse überhaupt compiliert?

Was ist wenn du 0x70 oder 0x38 nimmst?

von Ulrich Radig (Gast)


Lesenswert?

Also ist am I2C jetzt nur ein Teilnehmer mit der Adresse 0x0C? Alle 
anderen Slaves brauchen eine andere Adresse. Dann in der Software Slave 
Adresse 0x0C einstellen.

von Sven Müller (Gast)


Lesenswert?

Ulrich Radig schrieb:
> Also ist am I2C jetzt nur ein Teilnehmer mit der Adresse 0x0C?

Ja am I2C hängt nur ein Teilnehmer mit der Adresse 0x0C.

holger schrieb:
> Hast du das Programm mit der neuen Adresse überhaupt compiliert?

Ja habe ich :)

von Ulrich Radig (Gast)


Lesenswert?

In der Software habe ich aber 0x70 verwendet!!

von holger (Gast)


Lesenswert?

Was ist mit dem Rest meiner Frage?

>Was ist wenn du 0x70 oder 0x38 nimmst?

Deine I2C Adresse ist falsch. Das ist Fakt. Vergiss den Broadcast.

von Ulrich Radig (Gast)


Lesenswert?

Also wenn du 0x0C in der Software vom BLMC eingestellt hast versuche mal 
0x0C oder 0x0D!!!!!

von Sven Müller (Gast)


Lesenswert?

Ulrich Radig schrieb:
> In der Software habe ich aber 0x70 verwendet!!

Die Adresse habe ich angepasst.


holger schrieb:
> Was ist wenn du 0x70 oder 0x38 nimmst?

Geht auch beides nicht.

holger schrieb:
> Das ist Fakt. Vergiss den Broadcast.

Warum gibt es denn nach vielen Dokus einen Broadcast.

von Ulrich Radig (Gast)


Lesenswert?

Wenn ich das genau in Erinnerung habe ist 0x0C dann die Leseadresse und 
0x0D die Schreibadresse.

von Sven Müller (Gast)


Lesenswert?

Ulrich Radig schrieb:
> Wenn ich das genau in Erinnerung habe ist 0x0C dann die Leseadresse und
> 0x0D die Schreibadresse.

Die Software hängt das R/W Bit selber an.

von Ulrich Radig (Gast)


Lesenswert?

Also so sieht mein Testprogramm für 4 Motoren auf die Schnelle aus.
1
#include <avr/interrupt.h>
2
#include <avr/io.h>
3
#include <util/twi.h>
4
5
//Motoradresse
6
#define MOTOR_ADR 0x70
7
8
9
//############################################################################
10
//Hauptprogramm
11
int main (void) 
12
//############################################################################
13
{
14
  unsigned char pwm = 10;
15
  //Watchdog off
16
  asm("wdr");
17
  MCUSR &= ~(1<<WDRF);
18
  //Write logical one to WDCE and WDE
19
  WDTCSR |= (1<<WDCE) | (1<<WDE);
20
  //Turn off WDT
21
  WDTCSR = 0x00;
22
  
23
  TWSR = 0;
24
  TWBR = ((12000000/200000)-16)/2; 
25
  DDRC |= (1<<5); //SCL Output
26
  
27
  DDRB |= (1<<0);
28
  PORTB |= (1<<0);
29
  
30
  
31
  while(1)
32
  {
33
      //Start I2C
34
      TWCR = (1<<TWSTA) | (1<<TWEN) | (1<<TWINT);
35
      while (!(TWCR & (1<<TWINT)));
36
      //Write Motor Adresse
37
      TWSR = 0x00;
38
      TWDR = 0x40;
39
      TWCR = (1<<TWINT) | (1<<TWEN);
40
      while (!(TWCR & (1<<TWINT)));  
41
      //Write PWM
42
      TWSR = 0x00;
43
      TWDR = pwm;
44
      TWCR = (1<<TWINT) | (1<<TWEN);
45
      while (!(TWCR & (1<<TWINT)));
46
      //Stop I2C
47
      TWCR = (1<<TWEN) | (1<<TWSTO) | (1<<TWINT);
48
      for(unsigned long a = 0;a<10000;a++) asm("nop");
49
      
50
      //Start I2C
51
      TWCR = (1<<TWSTA) | (1<<TWEN) | (1<<TWINT);
52
      while (!(TWCR & (1<<TWINT)));
53
      //Write Motor Adresse
54
      TWSR = 0x00;
55
      TWDR = 0x50;
56
      TWCR = (1<<TWINT) | (1<<TWEN);
57
      while (!(TWCR & (1<<TWINT)));  
58
      //Write PWM
59
      TWSR = 0x00;
60
      TWDR = pwm;
61
      TWCR = (1<<TWINT) | (1<<TWEN);
62
      while (!(TWCR & (1<<TWINT)));
63
      //Stop I2C
64
      TWCR = (1<<TWEN) | (1<<TWSTO) | (1<<TWINT);
65
      for(unsigned long a = 0;a<10000;a++) asm("nop");
66
      
67
      //Start I2C
68
      TWCR = (1<<TWSTA) | (1<<TWEN) | (1<<TWINT);
69
      while (!(TWCR & (1<<TWINT)));
70
      //Write Motor Adresse
71
      TWSR = 0x00;
72
      TWDR = 0x60;
73
      TWCR = (1<<TWINT) | (1<<TWEN);
74
      while (!(TWCR & (1<<TWINT)));  
75
      //Write PWM
76
      TWSR = 0x00;
77
      TWDR = pwm;
78
      TWCR = (1<<TWINT) | (1<<TWEN);
79
      while (!(TWCR & (1<<TWINT)));
80
      //Stop I2C
81
      TWCR = (1<<TWEN) | (1<<TWSTO) | (1<<TWINT);
82
      for(unsigned long a = 0;a<10000;a++) asm("nop");
83
      
84
      //Start I2C
85
      TWCR = (1<<TWSTA) | (1<<TWEN) | (1<<TWINT);
86
      while (!(TWCR & (1<<TWINT)));
87
      //Write Motor Adresse
88
      TWSR = 0x00;
89
      TWDR = 0x70;
90
      TWCR = (1<<TWINT) | (1<<TWEN);
91
      while (!(TWCR & (1<<TWINT)));  
92
      //Write PWM
93
      TWSR = 0x00;
94
      TWDR = pwm;
95
      TWCR = (1<<TWINT) | (1<<TWEN);
96
      while (!(TWCR & (1<<TWINT)));
97
      //Stop I2C
98
      TWCR = (1<<TWEN) | (1<<TWSTO) | (1<<TWINT);
99
      for(unsigned long a = 0;a<10000;a++) asm("nop");
100
  }
101
}

von Ulrich Radig (Gast)


Lesenswert?

>> Die Software hängt das R/W Bit selber an.

habe ich auch gerade gesehen.

von Sven Müller (Gast)


Lesenswert?

Ulrich Radig schrieb:
> habe ich auch gerade gesehen.

Deswegen ist es glaube sinvoller nur DEC Zahlen anzugeben.

von holger (Gast)


Lesenswert?

>>In der BLMC Software ist 0x0C eingestellt

Nö ist sie nicht. Dann würde es ja funktionieren.

Oder vieleicht doch 0xC0? Dann versuch auch mal 0x60.

So langsam haben wir alle Adressen durch.

@Sven
Poste deinen aktuellen Code vom BLMC.

von Sven Müller (Gast)


Lesenswert?

holger schrieb:
> Poste deinen aktuellen Code vom BLMC.
1
/*----------------------------------------------------------------------------
2
 Copyright:      Ulrich Radig (mail@ulrichradig.de)
3
 Author:         Ulrich Radig
4
 Remarks:        
5
 known Problems: none
6
 Version:        23.06.2011
7
 Description:    Brushless Motor Controller for ATmega48/88/168
8
 
9
 Dieses Programm ist freie Software. Sie können es unter den Bedingungen der 
10
 GNU General Public License, wie von der Free Software Foundation veröffentlicht, 
11
 weitergeben und/oder modifizieren, entweder gemäß Version 2 der Lizenz oder 
12
 (nach Ihrer Option) jeder späteren Version. 
13
14
 Die Veröffentlichung dieses Programms erfolgt in der Hoffnung, 
15
 daß es Ihnen von Nutzen sein wird, aber OHNE IRGENDEINE GARANTIE, 
16
 sogar ohne die implizite Garantie der MARKTREIFE oder der VERWENDBARKEIT 
17
 FÜR EINEN BESTIMMTEN ZWECK. Details finden Sie in der GNU General Public License. 
18
19
 Sie sollten eine Kopie der GNU General Public License zusammen mit diesem 
20
 Programm erhalten haben. 
21
 Falls nicht, schreiben Sie an die Free Software Foundation, 
22
 Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. 
23
------------------------------------------------------------------------------*/
24
25
#include <avr/interrupt.h>
26
#include <avr/io.h>
27
#include <util/twi.h>
28
29
//Motoradresse
30
#define MOTOR_ADR 0x0C
31
32
//PHASE1 (U)
33
#define UH_DDR  DDRB |= (1<<3);
34
#define UH_ON  TCCR2A |= (1<<COM2A1);
35
#define UH_OFF  TCCR2A &= ~(1<<COM2A1);
36
37
//PHASE1 (U)
38
#define UL_DDR  DDRB |= (1<<1);
39
#define UL_ON  PORTB |= (1<<1);
40
#define UL_OFF  PORTB &= ~(1<<1);
41
42
43
//PHASE2 (V)
44
#define VH_DDR  DDRD |= (1<<5);
45
#define VH_ON  TCCR0A |= (1<<COM0B1);
46
#define VH_OFF  TCCR0A &= ~(1<<COM0B1);
47
48
//PHASE2 (V)
49
#define VL_DDR  DDRB |= (1<<2);
50
#define VL_ON  PORTB |= (1<<2);
51
#define VL_OFF  PORTB &= ~(1<<2);
52
53
54
//PHASE3 (W)
55
#define WH_DDR  DDRD |= (1<<3);
56
#define WH_ON  TCCR2A |= (1<<COM2B1);
57
#define WH_OFF  TCCR2A &= ~(1<<COM2B1);
58
59
//PHASE3 (W)
60
#define WL_DDR  DDRC |= (1<<3);
61
#define WL_ON  PORTC |= (1<<3);
62
#define WL_OFF  PORTC &= ~(1<<3);
63
64
65
#define PHASE_ALL_OFF  UH_OFF;UL_OFF;VH_OFF;VL_OFF;WH_OFF;WL_OFF;
66
67
#define SENSE_U    ADMUX = 0;
68
#define SENSE_V    ADMUX = 1;
69
#define SENSE_W    ADMUX = 2;
70
71
#define SENSE_H    (ACSR&(1<<ACO))
72
73
#define START_PWM   5
74
75
volatile unsigned long i2c_timeout = 0;
76
volatile unsigned char rx_pwm = 0;
77
volatile unsigned char rotor_state = 0;
78
volatile unsigned char rotor_run = 0;
79
80
//############################################################################
81
void next_commutate_state (unsigned char startup)
82
//############################################################################
83
{
84
  switch (rotor_state)
85
  {
86
    case (0):
87
      if(!SENSE_H || startup)
88
      {
89
        WH_OFF;
90
        UH_ON;
91
        SENSE_W;
92
        rotor_state = 1;
93
        TCNT1 = 1;
94
      }
95
      break;
96
97
    case (1):
98
      if(SENSE_H || startup)
99
      {
100
        VL_OFF;
101
        WL_ON;
102
        SENSE_V;
103
        rotor_state = 2;
104
        TCNT1 = 1;
105
      }
106
      break;
107
108
    case (2):
109
      if(!SENSE_H || startup)
110
      {
111
        UH_OFF;
112
        VH_ON;
113
        SENSE_U;
114
        rotor_state = 3;
115
        TCNT1 = 1;
116
      }
117
      break;
118
  
119
    case (3):
120
      if(SENSE_H || startup)
121
      {
122
        WL_OFF;
123
        UL_ON;
124
        SENSE_W;
125
        rotor_state = 4;
126
        TCNT1 = 1;
127
      }
128
      break;
129
130
    case (4):
131
      if(!SENSE_H || startup)
132
      {
133
        VH_OFF;
134
        WH_ON;
135
        SENSE_V;
136
        rotor_state = 5;
137
        TCNT1 = 1;
138
      }
139
      break;
140
141
    case (5):
142
      if(SENSE_H || startup)
143
      {
144
        UL_OFF;
145
        VL_ON;
146
        SENSE_U;
147
        rotor_state = 0;
148
        TCNT1 = 1;
149
      }
150
      break;
151
  }
152
}
153
154
//############################################################################
155
//back EMF zero crossing detection
156
ISR (ANALOG_COMP_vect) 
157
//############################################################################
158
{
159
  if(rotor_run == 200) next_commutate_state (0);
160
  
161
  rotor_run++;
162
  if(rotor_run > 200)
163
  {
164
    rotor_run = 200;
165
  }
166
}
167
168
//############################################################################
169
ISR (TIMER1_OVF_vect)
170
//############################################################################
171
{  
172
  next_commutate_state (1);
173
  rotor_run = 0;
174
  OCR2A = START_PWM;
175
  OCR2B = START_PWM;
176
  OCR0B = START_PWM;
177
}
178
179
//############################################################################
180
ISR (TWI_vect)
181
//############################################################################
182
{  
183
  switch (TWSR & 0xF8) //TW_STATUS 
184
  {  
185
    //Adresse empfangen
186
    case TW_SR_SLA_ACK:  
187
      TWCR |= (1<<TWINT);
188
      return;
189
      
190
    //Daten empfangen
191
    case TW_SR_DATA_ACK:
192
      rx_pwm = TWDR;
193
      TWCR |= (1<<TWINT);
194
      i2c_timeout = 0;
195
      return;
196
197
    //Bus-Fehler zurücksetzen 
198
    case TW_NO_INFO:
199
      TWCR |=(1<<TWSTO) | (1<<TWINT); 
200
201
    //Bus-Fehler zurücksetzen   
202
    case TW_BUS_ERROR:
203
      TWCR |=(1<<TWSTO) | (1<<TWINT); 
204
  }
205
  //Reset TW
206
  TWCR =(1<<TWEA) | (1<<TWINT) | (1<<TWEN) | (1<<TWIE);
207
}
208
209
//############################################################################
210
//Hauptprogramm
211
int main (void) 
212
//############################################################################
213
{
214
  //Watchdog on
215
  WDTCSR = (1<<WDCE) | (1<<WDE);
216
  
217
  //Motordriver output
218
  UH_DDR;
219
  VH_DDR;
220
  WH_DDR;
221
  UL_DDR;
222
  VL_DDR;
223
  WL_DDR;
224
    
225
  //PWM for UH, VH and WH (>32KHz)
226
  TCCR0A |= (1<<COM0B1|1<<WGM01|1<<WGM00);
227
  TCCR0B |= (1<<CS00);
228
  
229
  TCCR2A |= (1<<COM2A1|1<<COM2B1|1<<WGM21|1<<WGM20);
230
  TCCR2B |= (1<<CS20);
231
  
232
  //TIMER1 for start commutation or Back EMF lost
233
  TCCR1B |= (1<<CS11);
234
  TIMSK1 |= (1<<TOIE1);
235
236
  PHASE_ALL_OFF;
237
  
238
  //Comperator init for back EMF
239
  ADCSRB  |= (1<<ACME);
240
  DIDR1  |= (1<<AIN0D);
241
  ACSR  |= (1<<ACIE);
242
    
243
  //I2C Init
244
  TWAR = MOTOR_ADR & 0xFE;
245
    TWCR = (1<<TWINT)|(1<<TWEA)|(1<<TWEN)|(1<<TWIE);
246
  
247
  //Interrupts enabel
248
  sei();
249
  
250
251
  while(1)
252
  {  
253
    asm("wdr");
254
    if(rx_pwm > START_PWM)
255
    {
256
      ACSR |= (1<<ACIE);
257
      TIMSK1 |= (1<<TOIE1);
258
      
259
      if(rotor_run == 200)
260
      {
261
        OCR2A = rx_pwm;
262
        OCR2B = rx_pwm;
263
        OCR0B = rx_pwm;
264
      }
265
      i2c_timeout++;
266
      
267
      if(i2c_timeout>100000)
268
      {
269
        rx_pwm = 0;
270
      }
271
    }
272
    else
273
    {
274
      PHASE_ALL_OFF;
275
      ACSR&=~(1<<ACIE);
276
      TIMSK1 &= ~(1<<TOIE1);
277
    }
278
  }
279
}

von Sven Müller (Gast)


Lesenswert?

@Ulrich
Kann ich dich Morgen in meiner Mittagspause mal Anrufen?

von holger (Gast)


Lesenswert?

Und du bist sicher das du auch immer die aktuelle HEX Datei geflasht 
hast?

Ich mach dir mal einen Vorschlag:

Nimm das BLMC Programm. Lass die Adresse bei 0x0C.
Mach ein make clean, und neu übersetzen.
Nachsehen ob die HEX Datei das aktuelle Datum hat.
HEX Datei neu auswählen im Brenndialog. HEX Datei flashen.

Das gleiche machst du mit deinem Programm. Mit jedem einzelnen Schritt.
Einmal mit 0x0C und 0x06.

Wenn das nicht hilft, hilft dir nur noch Gott.

von Sven Müller (Gast)


Lesenswert?

Okay, mach ich mal ebende dauert so 10min :)

von Sven Müller (Gast)


Angehängte Dateien:

Lesenswert?

Hallo Ihr,

hier mal die Fuse-Bits im Anhang

von Ulrich Radig (Gast)


Lesenswert?

CKSEL3 noch rausnehmen

von Sven Müller (Gast)


Lesenswert?

Bedenke:
Alles OHNE Harken hat Bit=1

von Ulrich Radig (Gast)


Lesenswert?

Ja alles OHNE Harken ich kenne PonyProg

von Sven Müller (Gast)


Lesenswert?

Device clocking option            CKSEL3..0
Low power crystal oscillator      1111 - 1000
Full swing crystal oscillator     0111 - 0110
Low frequency crystal oscillator  0101 - 0100
Internal 128kHz RC oscillator     0011
Calibrated internal RC oscillator 0010
External clock                    0000
Reserved                          0001

von Ulrich Radig (Gast)


Lesenswert?

Glaub mir alles raus!

von Sven Müller (Gast)


Angehängte Dateien:

Lesenswert?

So habe jetzt alles raus :)

von Ulrich Radig (Gast)


Lesenswert?

OK

von Sven Müller (Gast)


Lesenswert?

Es geht immer noch nicht

Hello world...
0x08
0x18
0x28
Byte sent: 1
0x38
Byte sent: 2

bekomme ich per RS232 zurück

von holger (Gast)


Lesenswert?

Da das Thema gerade abschweift ein letzter Tip von mir.
Bei jedem Versuch vorher einfach mal das Gerät ausschalten.

Wenn der I2C Chip was falsches in den Hals bekommt könnte
er die beleidigte Leberwurst spielen bis man ihm den Saft
abdreht.

Ich bin dann mal weg.

von Ulrich Radig (Gast)


Lesenswert?

Aber dieses mal nicht mit der Adresse 0?

von Sven Müller (Gast)


Lesenswert?

Wenn ich andere aberssen nehme bekomme ich Could not start

von holger (Gast)


Lesenswert?

>Wenn ich andere aberssen nehme bekomme ich Could not start

Probier halt alle geraden Adressen von 0 bis 254 durch.
Eine wird schon passen.

von Sven Müller (Gast)


Lesenswert?

TWDR = (Address<<1) + TWIM_Type;
  TWCR = (1<<TWINT)|(1<<TWEN);
  printf("Addr: 0x%02x\n", TWDR);

Bringt bei Adresse 0x0C über RS232

Addr: 0x18

von holger (Gast)


Lesenswert?

>TWDR = (Address<<1) + TWIM_Type;
>Bringt bei Adresse 0x0C über RS232
>
>Addr: 0x18

0x0C << 1 ist nun mal 0x18. Schwachkopf.

von Ulrich Radig (Gast)


Lesenswert?

ändere mal die Zeile in TWDR = Address;

von Ulrich Radig (Gast)


Lesenswert?

;-)

von Sven Müller (Gast)


Lesenswert?

Rückgabe

0x08
Addr: 0x0c
0x00
Could not start TWI Bus for WRITE

von Sven Müller (Gast)


Lesenswert?

Es kann aber nicht damit zusammenhängen das ich kein Motor dran habe 
oder?

Bin nun erstmal im Bett melde mich morgen :)

von Ulrich Radig (Gast)


Angehängte Dateien:

Lesenswert?

Habe den Source Code von dir getestet (siehe Datei im Anhang) und es 
funktioniert. Mein Motor hat in der Software die Adresse 0x50!!

von Sven Müller (Gast)


Angehängte Dateien:

Lesenswert?

Hallo Ulrich magst du mal den ganzen Code testen?
Habe ihn in den Anhang genommen.

von Sven Müller (Gast)


Lesenswert?

Ich werde deinen Code mal heute Abend Testen :)
Und dann mein Ergebnis hier posten.

von Ulrich Radig (Gast)


Lesenswert?

Wie schon gesagt am SourceCode wird es vermutlich nicht liegen. Die 
Adresse 0 funktioniert nicht (Generall Call) das muß das Slave Device 
unterstützen. Du hattest da aber beim ersten mal bei Adresse 0 eine 
Antwort bekommen. Ich tippe da schwer auf einen Hardwarefehler.

Gruß
Uli

von Sven Müller (Gast)


Lesenswert?

Ich vermute das es am letzten Bit liegt welches mir durch R/W geklaut 
wird, werde es mal mit der Adresse 0x50 testen :)

von amateur (Gast)


Lesenswert?

Hast Du mal mit der Ticktack gespielt?

1 MHz  Takt ist flott, kann aber nicht jeder.
400KHz sind auch nicht ohne, möglicherweise kann auch das nicht jeder.
100KHz gehen auch noch recht gut.

Vergiss' nicht, Du (ATMega644) hast das sagen. Du gibst den Takt an.

Kann es sein, dass Du zwar Pull-Up-Widerstände aber keine 
Abschlusswiderstände hast?
Der Unterschied liegt in der Position bzw. im Layout.

von Abdul K. (ehydra) Benutzerseite


Lesenswert?

SDA mit SCL vertauscht? Poste deine Scope-Aufnahme!

von Sven Müller (Gast)


Lesenswert?

amateur schrieb:
> Vergiss' nicht, Du (ATMega644) hast das sagen. Du gibst den Takt an.

Ja ich weiß gebe 100kHz vor

amateur schrieb:
> Abschlusswiderstände hast?

noch nie bei I2C gesehen

Abdul K. schrieb:
> SDA mit SCL vertauscht? Poste deine Scope-Aufnahme!

Denn würde es ja nie gehen und nach durchgangs prüfungen ist alles 
richtig
Wenn ich ein scope hätte, mach es wenn es sein muss mit meiner 
Soundkarte

von Abdul K. (ehydra) Benutzerseite


Lesenswert?

Wir wollen nun das Scopebild sehen! Am Slave!

Es sind Pull-up-Rs.

Add: Soundkarte, hm. Weiß nicht ob das Sinn macht. Elektronikentwicklung 
ohne Scope ist einfach Blödsinn.

von Sven Müller (Gast)


Lesenswert?

Abdul K. schrieb:
> Elektronikentwicklung
> ohne Scope ist einfach Blödsinn.

Ich habe die nötigen Geräte sonst in der Schule, aber wir haben ferienn.
Zudem bin ich nicht reich und kann mir solche Geräte nicht leisten! Kein 
Grund jemanden zu verurteilen.

von Cyblord -. (cyblord)


Lesenswert?

Sven Müller schrieb:
> Abdul K. schrieb:
>> Elektronikentwicklung
>> ohne Scope ist einfach Blödsinn.
>
> Ich habe die nötigen Geräte sonst in der Schule, aber wir haben ferienn.
> Zudem bin ich nicht reich und kann mir solche Geräte nicht leisten! Kein
> Grund jemanden zu verurteilen.

Das sind ausreden!
Heute gibt es unglaublich günstige LAs. Es muss ja kein ausgewachsenes 
DSO sein.
Aber wenn man Embedded Entwicklung betreibt (auch privat) muss man einen 
Grundstock an Messgeräten haben. Das ist keine Frage des Geldes.
Ich kenne im Elektro-Modellflug Menschen mit 30 Jahren Erfahrung, ner 
10.000 Euro Maschine (3m Spannweite) aber haben zuhause kein Multimeter. 
Da kann man nur den Kopf schütteln. Auch fürs Hobby brauchts Ausrüstung!

Das ist heute alles saubillig und trotzdem fürs Hobby tauglich. Und wenn 
man mit seriellen Bussen spielt, sollte man irgendwie die Möglichkeit 
haben, diese zu sehen. Also einen LA. Ohne solche Technik macht man sich 
das Leben schwer und den anderen hier auch.

gruß cyblord

von Sven Müller (Gast)


Lesenswert?

cyblord ---- schrieb:
> Das sind ausreden!

Ich bin nich hier um mir etwas unterstellen zu lassen.

Ich erwarte ledigtlich ein bisschen hilfe und keine Unterstellungen.

von Sven Müller (Gast)


Lesenswert?

Hallo Ulrich,
das ganze geht jetzt nur i-wie läuft der motor so garnicht sauber -.-,

Mal läuft er, dann fiept er nur, denn ruckelt er rückwärts.. und immer 
wild durcheinander ich weiß net was da los ist

von Anspruch (Gast)


Lesenswert?

Wann hast du denn U.R.'s Zeug runtergeladen?
Wenn das nicht länger als 6 Monate her war, das hast du vielleicht noch 
Garantie!
Verklag ihn doch einfach.

Achtung, kann Spuren von Ironie enthalten!

von Joachim (Gast)


Lesenswert?

Na ja, ein Funken Wahrheit ist an dem was Cyblord und Abdul so schreiben 
schon dran.
Oszis gibts neu für 300 EUR, der EEV-Blogger hat sogar bei Ebay für sage 
und schreibe 19Aussie Dollar ein voll funktionsfähiges Hameg 
Speicheroszi aufgetrieben. Und wenn man clever ist kann man selbst mit 
einem alten Analog-Oszi + externer Triggerung und einem triggernden 
Port-Bit für ein Standbild sorgen um die Bits auf dem I2C-Bus 
abzuzählen.

Aber was solls. Schuld ist bei nicht funktionsfähigen Nachbauten ja 
sowieso eh immer derjenige der sich die Mühe machte sich etwas 
auszudenken und frei zu veröffentlichen.

von holger (Gast)


Lesenswert?

@Sven
>das ganze geht jetzt

Es wäre nett wenn du mal sagen könntest wo jetzt das Problem war.
Ansonsten kann man diesen Thread als nutzlosen Internetmüll auch
gleich löschen.

von Ulrich Radig (Gast)


Lesenswert?

Woran es jetzt gelegen hat wurde mir auch nicht verraten. Der geposteten 
Source Code funktionierte bei mir habe ich gestern Abend noch getestet. 
Das Ruckeln des Motors liegt am Delay (1000). Die Software ist für eine 
Drohne ausgelegt. Erhält der Motor nicht innerhalb einer gewissen Zeit 
ein neues Datenbyte bleibt dieser stehen.

Gruß
Uli

von Ulrich Radig (Gast)


Lesenswert?

so Ich gehe ins Bett, hier mit dem IPAD zu schreiben ist mist.

von Abdul K. (ehydra) Benutzerseite


Lesenswert?

Sven Müller schrieb:
> cyblord ---- schrieb:
>> Das sind ausreden!
>
> Ich bin nich hier um mir etwas unterstellen zu lassen.
>
> Ich erwarte ledigtlich ein bisschen hilfe und keine Unterstellungen.

Das darf natürlich deine Meinung sein und Verurteilung zu unterstellen, 
find ich auch etwas dreist! Für 10 Euro bekommt man einen LA. Einzige 
Einschränkung: Ohne Tricks keine analogen Werte.

Es läuft halt einfach so: Du bleibst auf deinem Standpunkt und ich helfe 
dir eben nicht mehr, denn meine Zeit ist auch kostbar.

von Sven Müller (Gast)


Lesenswert?

holger schrieb:
> Es wäre nett wenn du mal sagen könntest wo jetzt das Problem war.

Das Problem lag bei der Adresse das Motors,
das runtersetzen des Delays hat schon zu einer Besserung geführt,
aber bei werten wie z.B. 255 fiept der Motor nur und bei 200 springt er 
auch nur an wenn ich in anschupse.

von Sven Müller (Gast)


Angehängte Dateien:

Lesenswert?

So hier mal Screens vom Soundkarten scope.

die mit sind gemessen mit Motor die ohne sind gemessen ohne Motor jewals

L1_L3 und L2_L3, wobei die rote Linie immer L3 zeigt

von Ulrich Radig (Gast)


Lesenswert?

Und wenn du zuerst mal langsam mit dem Wert 50 Anfägst?? Wie groß ist 
der Elko auf dem BLMC??

von Sven Müller (Gast)


Lesenswert?

Ulrich Radig schrieb:
> wie groß ist der Elko auf dem BLMC

16V 220µF

von Sven Müller (Gast)


Lesenswert?

So habe gerade nen anderen Treiber getestet, dieser ging... und ein 
anderer spackte wieder :/

von Sven Müller (Gast)


Lesenswert?

ambesten läuft der treiber mit einem 18.432MHz Quarz hm...

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.