Code:
// RA2 steuert RP6 1.11.2010 mic
// Das I2C-Masterdemo6 des m32 angepasst an das arm64-Modul.
// Eine Ergänzung in der Abfrage des Keypads ermöglicht gleichzeitige Bewegungen
// aller Servos und des RP6.
// Auf dem RP6 läuft das unveränderte I2C-Slave-Demo.
// Verbindung zwischen RP6-XBUS Pin8(E_INT), Pin10(SCL), Pin12(SDA) und Pin14(GND)
// und IIC Pin 8-14 auf dem arm64. Beide Boards werden getrennt versorgt.
// PollSwitch16() liefert ein 16bit Abbild der Tasten
// scan_keyboard1() liefert die Tastennummer mit geänderter Portabfrage
// Infos zum Portexpander
// http://www.mikrocontroller.net/artic...pander_PCF8574
#include "RobotArmBaseLib.h"
#include "RP6I2CmasterTWI.h"
#include "RP6Control_I2CMasterLib.h"
#define I2C_RP6_BASE_ADR 10 // The default address of the Slave Controller (RP6)
/*****************************************************************************/
// I2C Error handler
/**
* This function gets called automatically if there was an I2C Error like
* the slave sent a "not acknowledge" (NACK, error codes e.g. 0x20 or 0x30).
* The most common mistakes are:
* - using the wrong address for the slave
* - slave not active or not connected to the I2C-Bus
* - too fast requests for a slower slave
* Be sure to check this if you get I2C errors!
*/
void I2C_transmissionError(uint8_t errorState)
{
writeString_P("\nI2C ERROR - TWI STATE: 0x");
writeInteger(errorState, HEX);
writeChar('\n');
}
/*****************************************************************************/
// Motor function
uint8_t transmit_buffer[10]; // temporary transmit buffer
// A global variable saves space on the heap...
#define CMD_ROTATE 8
#define LEFT 2
#define RIGHT 3
/**
* Rotate function - you can define nearly the same functions as you have on
* the RP6 and just forward the commands with I2C Bus transfers...
* We will make an improved version of this and other functions in another example!
*/
void RP6_rotate(uint8_t desired_speed, uint8_t dir, uint16_t angle)
{
transmit_buffer[0] = 0;
transmit_buffer[1] = CMD_ROTATE;
transmit_buffer[2] = desired_speed;
transmit_buffer[3] = dir;
transmit_buffer[4] = ((angle>>8) & 0xFF);
transmit_buffer[5] = (angle & 0xFF);
I2CTWI_transmitBytes(I2C_RP6_BASE_ADR, transmit_buffer, 6 );
}
#define CMD_MOVE 7
#define FWD 0
#define BWD 1
void RP6_move(uint8_t desired_speed, uint8_t dir, uint16_t ticks)
{
transmit_buffer[0] = 0;
transmit_buffer[1] = CMD_MOVE;
transmit_buffer[2] = desired_speed;
transmit_buffer[3] = dir;
transmit_buffer[4] = ((ticks>>8) & 0xFF);
transmit_buffer[5] = (ticks & 0xFF);
I2CTWI_transmitBytes(I2C_RP6_BASE_ADR, transmit_buffer, 6 );
}
/*****************************************************************************/
// Read all registers function
uint8_t RP6data[32]; // This array will contain all register values of RP6
// after you called readAllRegisters()
// It is better to keep such big arrays GLOBAL as
// they otherwise fill up the stack in memory...
/**
* This function reads ALL registers available in the standard I2C Bus Slave
* Example program for the Robot Base and outputs their values on the serial interface.
* You will see a lot of zeros when the Motors are not running. The main values that are not
* zero are the two Light Sensors and the two free ADC Channels.
*/
void readAllRegisters(void)
{
I2CTWI_transmitByte(I2C_RP6_BASE_ADR, 0); // Start with register 0...
I2CTWI_readBytes(I2C_RP6_BASE_ADR,RP6data, 30); // and read all 30 registers up to
// register Number 29 !
// Now we output the Data we have just read on the serial interface:
writeString_P("\nREADING ALL RP6 REGISTERS:");
uint8_t i = 0;
for(i = 0; i < 30; i++)
{
if(i % 8 == 0) // add some newline chars otherwise everything
writeChar('\n'); // is printed on ONE single line...
else
writeString_P(" | ");
writeChar('#');
writeIntegerLength(i,DEC,2);
writeChar(':');
writeIntegerLength(RP6data[i],DEC,3);
}
writeChar('\n');
}
/**
* Here we demonstrate how to read a few specific registers.
* It is just the same as above, but we only read 4 registers and
* start with register Number 13...
* We also show how to combine values from high and low registers
* back together to a 16 Bit value...
*/
void readLightSensors(void)
{
uint8_t lightSens[4];
I2CTWI_transmitByte(I2C_RP6_BASE_ADR, 13); // Start with register 13 (LSL_L)...
I2CTWI_readBytes(I2C_RP6_BASE_ADR, lightSens, 4); // and read all 4 registers up to
// register Number 16 (LSR_H) !
writeString_P("Light Sensor registers:\n");
writeString_P(" | LSL_L:"); writeInteger(lightSens[0], DEC);
writeString_P(" | LSL_H:"); writeInteger(lightSens[1], DEC);
writeString_P(" | LSR_L:"); writeInteger(lightSens[2], DEC);
writeString_P(" | LSR_H:"); writeInteger(lightSens[3], DEC);
writeString_P("\n\n Light Sensor Values:");
writeString_P(" | LSL:"); writeInteger(lightSens[0] + (lightSens[1]<<8), DEC);
writeString_P(" | LSR:"); writeInteger(lightSens[2] + (lightSens[3]<<8), DEC);
writeChar('\n');
//setCursorPosLCD(1, 3);
//writeIntegerLengthLCD(lightSens[0] + (lightSens[1]<<8), DEC, 4);
//setCursorPosLCD(1, 11);
//writeIntegerLengthLCD(lightSens[2] + (lightSens[3]<<8), DEC, 4);
}
/*****************************************************************************/
// Main function - The program starts here:
int PollSwitch16(void)
{
int i, j, mask=0, x=0;
for(j=0; j<4; j++)
{
DDRA = (1<<j); // PAj auf Ausgang
PORTA = ~(1<<j); // PA7 bis PA4 ist Eingang mit Pullup, PAj ist LOW (Tilde!)
sleep(10); // Warten auf Pegel
x=(PINA>>4); // Eingang PA7-4 wird zu Bit3-0 in x
for(i=0; i<4; i++) // Bits 0-3 überprüfen
if(!(x & (1<<i))) // Wenn Eingang low ist wurde die Taste gedrückt
mask += (1 << (i*4)) * (1<<j); // entsprechendes Bit in Maske setzen
}
PORTA = 0; // Port A deaktivieren
DDRA = 0;
return(mask);
}
int scan_keyboard1(void)
{
int i, mask = PollSwitch16();
for(i=0; i<16; i++) // wurde eine Taste gedrückt?
{
if(mask & (1<<i)) // Taste i gedrückt?
{
if(mask & ~(1<<i))
return(0); // mehrere Tasten gleichzeitig gedrückt!
else
return(i+1); // Tastennummer zurückgeben
}
}
return(0); // keine Taste gedrückt
}
int speed;
void Event( int x )
{
if(x == 0)
{
if(PING & LED_GREEN) PowerLEDoff(); else PowerLEDgreen();
mSleep(300);
}
else
{
PowerLEDred();
//Power_Servos();
if(x & (1<<0)) { Pos_Servo_1-=speed; Power_Servos();}
if(x & (1<<1)) { Pos_Servo_1+=speed; }
if(x & (1<<2)) { Pos_Servo_2+=speed; } // Drehrichtung invers!
if(x & (1<<3)) { Pos_Servo_2-=speed; }
if(x & (1<<4)) { Pos_Servo_3-=speed; }
if(x & (1<<5)) { Pos_Servo_3+=speed; }
if(x & (1<<6)) { Pos_Servo_4-=speed; }
if(x & (1<<7)) { Pos_Servo_4+=speed; }
if(x & (1<<8)) { Pos_Servo_5-=speed; Pos_Servo_6-=speed; }
if(x & (1<<9)) { Pos_Servo_5+=speed; Pos_Servo_6+=speed; }
if(x & (1<<10)) { PowerLEDorange(); speed=5; }
if(x & (1<<11)) { PowerLEDorange(); speed=1; }
if(x & (1<<12)) { RP6_rotate(35,BWD,40); }
if(x & (1<<13)) { RP6_rotate(35,FWD,40); }
if(x & (1<<14)) { RP6_rotate(35,RIGHT,40); }
if(x & (1<<15)) { RP6_rotate(35,LEFT,40); }
}
/*
writeInteger(Pos_Servo_1, 10);
writeString_P(" | ");
writeInteger(Pos_Servo_2, 10);
writeString_P(" | ");
writeInteger(Pos_Servo_3, 10);
writeString_P(" | ");
writeInteger(Pos_Servo_4, 10);
writeString_P(" | ");
writeInteger(Pos_Servo_5, 10);
writeString_P(" | ");
writeInteger(Pos_Servo_6, 10);
writeString_P("\n");
*/
}
int Batterie(void)
{
#define BATTERIE 6
ADMUX = (1 << REFS0) | (1 << REFS1) | BATTERIE; // internal 2.56V reference with external capacitor
ADCSRA |= (1 << ADSC); // Start conversion
while (!(ADCSRA & (1 << ADIF))); // wait for conversion complete
ADCSRA |= (1 << ADIF); // clear ADCIF
return ADCL + (ADCH << 8);
}
void printUBat(uint16_t ubat)
{
writeIntegerLength((((ubat/204.8f)+0.1f)), DEC, 2);
writeChar('.');
writeIntegerLength((((ubat/2.048f)+10)), DEC, 2);
writeChar('V');
}
int main(void)
{
initRobotBase();
PORTA = 0; // Port A deaktivieren
DDRA = 0;
writeString_P("\n\nRA2 arm64 I2C Master Example Program! 3.11.2010 mic\n\n");
int ubat = readADC(ADC_UBAT);
printUBat(ubat);
writeString_P("\n");
// IMPORTANT:
I2CTWI_initMaster(100); // Initialize the TWI Module for Master operation
// with 100kHz SCL Frequency
// Register the event handlers:
I2CTWI_setTransmissionErrorHandler(I2C_transmissionError);
//char counter = 1;
//Start_position(); //Use this function to set the servomotor in the centre.
//This function must be called before using Power_Servos();
speed=1; //Speed for servo from '1'(slow) - '10'(fast!)
Pos_Servo_1=1500;
Pos_Servo_2=1530;
Pos_Servo_3=1100;
Pos_Servo_4=1640;
Pos_Servo_5=580;
Pos_Servo_6=580;
//Power_Servos(); //Use this function to power the servo motors on
while(true)
{
Event(PollSwitch16());
/*
if(scan_keyboard1())
{
writeInteger(scan_keyboard1(), 10);
writeChar('\n');
switch(0)
{
case 1: // Increment a counter and send value to LEDs of the
// Slave Controller:
//setLEDs(0b0001);
//showScreenLCD("INCREMENT", "LED COUNTER");
I2CTWI_transmit3Bytes(I2C_RP6_BASE_ADR, 0, 3, counter);
counter++;
break;
case 2: // Read and display ALL registers of the slave controller:
//setLEDs(0b0010);
//showScreenLCD("READ ALL RP6", "REGISTERS");
readAllRegisters();
break;
case 3: // Read the light sensors and show value on display:
//setLEDs(0b0100);
//showScreenLCD("LIGHT SENSORS:", "L: R:");
readLightSensors();
break;
case 4: // Rotate a very small distance to the left:
//setLEDs(0b1000);
//showScreenLCD("ROTATE A BIT...", "... LEFT!");
RP6_rotate(35,LEFT,40);
break;
case 5: // Rotate a very small distance to the right:
//setLEDs(0b1001);
//showScreenLCD("ROTATE A BIT...", "... RIGHT!");
RP6_rotate(35,RIGHT,40);
break;
}
while(scan_keyboard1());
}
*/
}
return 0;
}
Außerdem mußte ich meine Tastenabfrage ändern, weil das Keypad nicht vollständig bestückt war:
Lesezeichen