I want to set DALI scene with Arduino uno. but I don't know which command should be sent?
which command should be sent twice?
and Which command should be sent first?
According with DALI communication protocol, your frame should be like this:
frame[0] = 0x83;
frame[1] = 0x00;
frame[2] = ....; // DALI device id
frame[3] = ....; // 10 + scene number
frame[4] = frame[1] ^ frame[2] ^ frame[3] ^ frame[4]; // Checksum
It is just one command, 5 Bytes total.
Related
I am using a STM32F415RGT6 embedded in the 1Bitsy Board. I want to set up the I2C Peripheral in order to read some data from a sensor. I am using the stm32f4 standard peripheral library.
My example code:
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOB, ENABLE);
GPIO_InitTypeDef gpioInit;
GPIO_StructInit(&gpioInit);
gpioInit.GPIO_Mode = GPIO_Mode_AF;
gpioInit.GPIO_Pin = GPIO_Pin_6 | GPIO_Pin_7;
gpioInit.GPIO_PuPd = GPIO_PuPd_UP;
gpioInit.GPIO_Speed = GPIO_Speed_25MHz;
GPIO_PinAFConfig(GPIOB, GPIO_PinSource6, GPIO_AF_I2C1);
GPIO_PinAFConfig(GPIOB, GPIO_PinSource7, GPIO_AF_I2C1);
GPIO_Init(GPIOB, &gpioInit);
RCC_APB1PeriphClockCmd(RCC_APB1Periph_I2C1, ENABLE);
I2C_DeInit(I2C1);
I2C_InitTypeDef I2C_InitStructure;
I2C_StructInit(&I2C_InitStructure);
/* I2C configuration */
I2C_InitStructure.I2C_Mode = I2C_Mode_I2C;
I2C_InitStructure.I2C_ClockSpeed = 100000;
I2C_InitStructure.I2C_DutyCycle = I2C_DutyCycle_2;
I2C_InitStructure.I2C_OwnAddress1 = 0x01;
I2C_InitStructure.I2C_Ack = I2C_Ack_Enable;
I2C_InitStructure.I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_7bit;
I2C_Init(I2C1, &I2C_InitStructure);
I2C_Cmd(I2C1, ENABLE);
while (I2C_GetFlagStatus(I2C1, I2C_FLAG_BUSY));
/* Generate Start, send the address and wait for ACK */
I2C_GenerateSTART(I2C1, ENABLE);
while (!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_MODE_SELECT));
I2C_Send7bitAddress(I2C1, 0xE0, I2C_Direction_Transmitter);
while (!I2C_CheckEvent(I2C1,I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED));
After that I want to write a 0x00, but the code always hangs in the last line, apparently the Master never reads the acknowledge. The I2C status registers always read:
I2C1 -> SR1 = 1024
I2C1 -> SR2 = 3
which means that the Acknowledge Failure bit is always set. If I analyze it using my Saleae I get the following:
The Slave sends the ACK, but the STM32F415 cannot read it.
The weird thing: If I try the same code on my F407 - Disco (only with clock set to 400khz, but it's the same behaviour on both MCUs regardless of Speed), it works flawlessly:
All other peripherals work fine. I already tried several workarounds, but the AF bit is always set, regardless of method. I hope you can help me.
P.S: I have tried with and without additional pullups and the I2C Slave Address is fine, because it works with STM32F0, STM32F4-DISCO and Atmel Mcus.
Best Regards and Thanks in advance!
I have an issue related to "Transmission" from microcontroller. Microcontroller is able to receive, but unable to transmit.
this is an additional issue to my previously asked question [here]
Below is the max485 interface with microcontroller :
Here is my code snapshot :
// RS485
TRISBbits.TRISB6 = INPUT_PIN; // RX - RB6/RP38 PIN<42>
TRISBbits.TRISB7 = OUTPUT_PIN; // TX - RB7/RP39 PIN<43>
TRISBbits.TRISB8 = OUTPUT_PIN; // !RE/DE Control Pin RB8/RP40 PIN<44>
// RS485 Config
#define RS485_TX PORTBbits.RB6 // RS485 Transmitter
#define RS485_RX LATBbits.LATB7 // RS485 Reciever
#define RS485_CTRL LATBbits.LATB8 // RS485 Control Pin
// UART ISR
void __attribute__((interrupt, no_auto_psv)) _U4RXInterrupt(void)
{
rs485Char = U4RXREG;
RS485_CTRL = 1; // Enable driver
U4TXREG = rs485Char;
RS485_CTRL = 0; // disable driver RE/DO
}
void InitRs485(void){
// configure U1MODE
U4MODEbits.UARTEN = 0; // Bit15 TX, RX DISABLED, ENABLE at end of func
U4MODEbits.URXINV = 1; // 1:URXINV Idle state is '0' ; 0=UxRX Idle state is '1';
U4MODEbits.ABAUD = 0; // Bit5 No Auto baud (would require sending '55')
U4MODEbits.BRGH = 0; // Bit3 16 clocks per bit period
U4MODEbits.PDSEL = 0; // 0 : 8 bit,no parity; 1 : 8 bit,even parity; 2 : 8 bit,odd parity; 3 : 9 bit,no Parity
U4MODEbits.STSEL = 1; // 1 : 2 Stop bits; 0 : 1 Stop bits
U4MODEbits.LPBACK = 0; // Lookback disable
U4STAbits.URXISEL = 0; // Interrupt flag bit is set when a character is received
// Load a value into Baud Rate Generator.
U4BRG = BRGVAL_RS485; // 60Mhz osc, 9600 Baud
// Load all values in for U1STA SFR
U4STAbits.UTXISEL1 = 0; // Bit15 Int when Char is transferred (1/2 config!)
U4STAbits.UTXISEL0 = 0; // Bit13 Other half of Bit15
U4STAbits.UTXINV = 1; // 1:UxTX Idle state is '0' ; 0=UxTX Idle state is '1';
U4STAbits.UTXBRK = 0; // Bit11 Disabled
U4STAbits.UTXEN = 0; // Bit10 TX pins controlled by peripheral
U4STAbits.URXISEL = 0; // Bits6,7 Int. on character received
IPC22bits.U4RXIP = 7;
IPC22bits.U4TXIP = 7;
IFS5bits.U4TXIF = 0; // Clear the Transmit Interrupt Flag
IEC5bits.U4TXIE = 0; // Enable Transmit Interrupts
IFS5bits.U4RXIF = 0; // Clear the Receive Interrupt Flag
IEC5bits.U4RXIE = 0; // Enable Receive Interrupts
RPOR2bits.RP39R = 0x1D; // dsPic33EP512GM604 => RP39 as U4TX PIN<43>
_U4RXR = 38; // dsPic33EP512GM604 => RP38 as U4RX PIN<42>
U4MODEbits.UARTEN = 1; // And turn the peripheral on
U4STAbits.UTXEN = 1;
// Hardware control bits
IEC5bits.U4RXIE = 1;
IFS5bits.U4RXIF = 0;
RS485_CTRL = 0; // disable driver; Receive Enable
}
In above code, I have a UART Receive Interrupt routine.
Whenever any character is received, UART ISR receives it, but unable to transmit anything back.
In my ISR, I am trying to send back the character received.
This issue might be related to the max485 control pins (!RE/DE), which is referred as RS485_CTRL in my code.
So, I tried to rectify the issue as below :
If ISR is written as
rs485Char = U4RXREG;
RS485_CTRL = 1; // Enable driver
U4TXREG = rs485Char;
then microcontroller transmit 2Bytes, first one is the character recieved, second byte is a false byte ie.0x00.Thereafter no character is received by the ISR.
If ISR is written as :
rs485Char = U4RXREG;
RS485_CTRL = 0; // Disable driver
U4TXREG = rs485Char;
RS485_CTRL = 1; // Enable driver
than it transmit a first character recieved. But there after ISR gets into infinite loop ie. receives a NULL character and transmits a NULL character.
As per the RS485 implementation rules,
RS485_CTRL (!RE/DE) should be 0 to receive data
RS485_CTRL (!RE/DE) should be 1 to transmit data.
My microcontroller is acting as a SLAVE, so by default I have kept it into listening mode. But when data is received I am unable to transmit.
Pls help me get my mistake identified ???
As per the suggestion given by #linuxfan, Correct ISR should be as below :
// UART ISR
void __attribute__((interrupt, no_auto_psv)) _U4RXInterrupt(void)
{
rs485Char = U4RXREG;
RS485_CTRL = 1; // Enable driver
U4TXREG = rs485Char;
while(!U4STAbits.TRMT); // wait until character is transffered successfully
RS485_CTRL = 0; // disable driver RE/DO
}
Now my code is working fine as expected.
The LTE-485 (RS-485 line driver) has a "driver enable pin" which must be asserted in order to transmit. You must assert it just before starting to send a character, and you must de-assert it after the last byte has finished transmission (you de-assert it in order to be able to receive data, or to let some other device to drive the bus. If you don't want to receive, and you don't have any other device willing to transmit, you can keep it asserted).
In your code there is:
RS485_CTRL = 1; // Enable driver
U4TXREG = rs485Char;
You enable the driver with RS485_CTRL=1, then you load the UART shift register, but perhaps you don't wait the time all the data is shifted out.
In order to wait for the data to shift out, you can load a timer which will fire after a fixed time: the time a character, 10 bits probably, takes to be shifted out at the baud rate you programmed. Each time you transmit a character, start this timer. When the timer expires, disable the OE (output driver enable).
Another way is to wait for the reception of the character you just sent out. You load the transmit register; when all the bits are shifted out, you will receive the character (RS-485 is a bus). At that time, you can disable the transmitter if you want. Of course, this is not very good if you want to transmit a stream of characters back-to-back. Moreover, in your hardware setup you can't do that because you disable the receiver (the receiver enable and driver enable are shorted together).
But you can do what I think is the best. When you transmit a char, enable the driver of the interface OE; then use the TX interrupt of your UART to transmit the next character (if any), or de-assert the driver if there is nothing more to transmit. Beware to use the right transmitting interrupt: some UART (I don't know the one you are using) has buffering - you need the interrupt that fires when the datum has shifted out, not the one which says "you can load more data".
NOTE ASIDE: you are using a DB9 connector, using the pins 2 and 3, and labelling them TX and RX. Well, there is NO TX and RX wires in the RS-485: the two wires are named A and B, and both carry the same, balanced signal. These wires are used to receive data, when left floating, and the same wires are used to transmit data, if driven by the LTC-485 driver. You can very well enable the transmitting driver and keep to "listen" on the wires. You will receive back what you just transmitted (and this can also diagnose that the wires are shorted or the driver is blown). You can choose to use a connector often used for RS-232, and you can also choose to use the same pins 2 and 3 as the RS-232, but in no way an RS-485 can be assimilated to an RS-232.
Examples of writing to a port seem to always use the port number as a constant, eg,
OCR2A = 180;
How do you write to the port when the port is unknown until run time. For example,
int port = (buttonPressed) ? 0x3b : 0x3c;
portWrite( port, 180 );
What I cannot find is the funtion portWrite(). Does something like that exist?
Robert's answer has some imprecise assertions and an incomplete answer.
Writing directly to port registers you can ruin other settings of the port and sometimes cause permanent damage to controller.
Can ruin other settings: true, you have to know what you are doing (for instance what pins are on the port you are manipulating, and know what are the functions you want to keep.
Can cause permanent damage: not really, or better not because of the port manipulation. If you wire a short circuit to ground and then set it as an output to 1, you can damage it whether you are using the port register or the digitalwrite. You have to be careful in both ways.
Now, returning to your problem, the enumeration is one way, but since the PORTB, PORTC, PORTD are just short name for values, you can set a variable and then use it to indirectly access it.
The type for this kind of variable is a volatile pointer to a byte (volatile means that write and read operations cannot be optimized by the compiler, since the value can change even between two operations):
volatile uint8_t *variablePortRegister;
You just have to load it with the address (so with the & symbol) of the register you want to change:
variablePortRegister = &PORTC;
then use the pointer to change the value
PORTC = 0x12;
becomes
(*variablePortRegister) = 0x12;
This is a short example. For it to work, connect a LED with resistor on arduino pin 5 (bit 5 of PORTD). The LED on the board (labeled L) is connected to pin 13 (bit 5 of PORTB).
The sketch will make one of the two leds blink for five times, then switch to the other. Only port manipulation instructions are used, and you can find that the way to read the port is the same as the one to write it.
volatile uint8_t *myportreg;
unsigned long lastTime;
uint8_t counter;
void setup() {
DDRB |= 0x20;
DDRD |= 0x20;
PORTB = 0;
PORTD = 0;
counter = 99; // trigger the register change immediately
}
void loop() {
if (counter >= 10)
{
counter = 0;
if (myportreg == &PORTD)
myportreg = &PORTB;
else
myportreg = &PORTD;
}
if ((millis() - lastTime) > 500)
{
lastTime = millis();
// change bit 5 of register
*myportreg = 0x20 ^ (*myportreg);
counter++;
}
}
EDIT: as Robert pointed out, it's much better to "use" just the pins you need (in this case, bit 5 of port B and D) rather than setting the whole port; this way you minimize the risk of screwing up something else. This edit is already included in the above code, so the code is correct
The port is a bit in one particular register. If you know the register and the position of the port in that particular register you can try this:
register = (1<<port) || register
to set the port to 1 and
register = (1<<port)^-1 && register
to set the port to 0.
Of course, you will need a switch somewhere to determine the register and the bit of the port in the register given the port name.
I need to transfer data serially from AT89s52 to Hyperterminal of PC.
For that I made a sample program to print "Hello" on the hyperterminal of my PC by programming the below given code inside 89s52 microcontroller and connecting it to my PC via serial port. Now when I am opening hyperterminal for the respective port, I should be seeing "Hello" printed on the screen multiple times, but what actually I am seeing is some garbage data getting printed.
This is the code I have used.
#include < AT89X52.H>
#include < STDLIB.H>
#include < STDIO.H>
unsigned int i;
void main (void)
{
TMOD = 0x20;
SCON = 0x50;
TH1 = 0xFD;
TL1 = 0xFD;
TR1 = 1;
TI = 1;
P1 = 0;
while (1)
{
puts("Hello\r");
P1 ^= 0x01; /* Toggle P1.0 each time we print */
for(i=0;i<25000;i++);
}
}
In the Hyper terminal I am not getting correct output i.e. Hello. Instead I am seeing some Garbage characters..
Can anybody help on this please..?
Can you See P1 is toggling? I would rather send a single character first and observe what is sending by using an oscilloscope. You should see a digital signal corresponding to the ASCII value of the character being split-out from the TX pin of the micro. Also you can check the baud rate (exact value) by using the scope. If you are convinced that the correct value is sent at the right baud rate it is most likely that you got a bad connection or perhaps the baud rate should slightly be changed.
I try to control a stepper motor with a program that uses a protocol (see below)
I am able to control the stepper with the Accelstepper (see below) but have no idea how i can program the Arduino so it is able to communicate according te protocol through the serial port.
#include <AccelStepper.h>
// Define a stepper and the pins it will use
AccelStepper stepper(1, 3, 4);
int pos = 8192;
void setup()
{
stepper.setMaxSpeed(5000);
stepper.setAcceleration(1500);
}
void loop()
{
if (stepper.distanceToGo() == 0)
{
delay(500);
pos = -pos;
stepper.moveTo(pos);
}
stepper.run();
}
All commands sent to the rotary table are in simple character format including the motor numbers. Only the parts marked as xxx passed to the table as byte data. For example if you want table 1 rotate 4 steps instead of passing "I1M004" you pass "I1M" + (char)0 + (char)0 + (char)4
In general all commands get a reply in the form of: ^XXXXXX
Commands
V
Request the status of the rotary table. Usual reply would be ^R1R2R3R4 indicating rotary 1 ready, rotary 2 ready, etc. ^B1xxxR2R3R4 means rotary 1 is busy where xxx are 3 bytes indicates how many steps the rotary still has to perform.
SmMxxx
Sets the speed of the motor m to xxx, where xxx is a 3 bytes of data indicating the speed. Example code: port.Write("S1M" + (char)0 + (char)6 + (char)255); // set motor 1 to speed 1791. The standard speed range of our rotary table is: 0x000001 to 0x0012FF (1 to 4863). Controller will respond with ^mxx mirroring the motor number and 2 last bytes of speed setting.
ImMxxx
Turns motor m xxx number of steps. Controller will acknowledge with ^Bmxxx
DmCWLO
Set motor number m to rotate clockwise (So each consecutive command to rotate the motor m will rotate it clockwise).
DmCWHi
Sets rotary m to rotate counterclockwise.
EmHALT
Rotary m stop.
Rotary Sample Command Sequence
Motor numbers are passed as characters but the number of steps and speed are passed as 3 bytes of binary for simplicity.
send: V reply: ^R1R2R3R4
send: S1M1791 reply: ^191
send: D1CWLO reply: ^
send: I1M100 reply: ^B1100
I had a similar project for my dissertation work where I controlled an inverted pendulum from a PC via an arduino uno. I'm assuming you have a PC program what sends out the commands to the arduino, and the problem is to receive and interpret it on the Arduino board.
I wrote the code below with major help (some copy paste modify) from here
It basically opens the com port and then listens to the incoming commands from the PC. When a command is received, it breaks it up (the incoming commands come in a #00parameter format). All commands start with #. The following 2 digits define the command itself, and the following text/numbers are the parameters for the command.
Once the command and its parameters are known, the actual process related to the command can be executed. In your case this supposed to be the motor control related to the incoming commands. The below code obviously needs to be updated to match with your motor control functions, but the incoming command handling works just fine.
String inputString = ""; // a string to hold incoming data
boolean stringComplete = false; // whether the incloming string is complete
float kp = 10; //sample parameter 1
float kd = 5; //sample parameter 2
float ki = 2; //sample parameter 3
void setup()
{
Serial.begin(9600); //Start serial communication
inputString.reserve(200); //Reserves 200 bytes for the string
}
void loop()
{
//This becomes true when the serial port receives a "\n" character (end of line)
if (stringComplete)
{
SerialProc(); //the function which runs when a full line is received
inputString = ""; //once processed, the string is cleared
stringComplete = false; //set flag to false to indicate there is nothing in the buffer waiting
}
}
void serialEvent() //This serial event runs between each loop cycles
{
while (Serial.available()) //if there is anything in the incoming buffer this while loop runs
{
// get the next new byte:
char inChar = (char)Serial.read();
// add it to the inputString:
inputString += inChar;
// if the incoming character is a newline, set a flag
// so the main loop can do something about it:
if (inChar == '\n')
{
stringComplete = true; //This indicates the line is complete, and the main program can process it
}
}
}
void SerialProc() //the function which processes the incoming commands. It needs to be modified to your needs
{
//cmd is the first three characters of the incoming string / line
String cmd = inputString.substring(0,3); //first three characters in incoming string specifies the command
//param is the rest of the string to the end of the line (excluding the first three characters)
String param = inputString.substring(3, inputString.length()); //rest of incoming string is making up the parameter
//creating a buffer as an array of characters, same size as the length of the parameters string
char buf[param.length()];
//moving the parameters from string to the char array
param.toCharArray(buf,param.length());
//the above string to char array conversion is required for the string to float
//conversion below (atof)
//the below part is the command execution. Could have used a switch below, but the series of ifs
//just did the trick
if (cmd == "#00")
SendReply(); //Executing command 1
else if (cmd == "#01")
kp = atof(buf); //executing command 2 (setting parameter kp)
else if (cmd == "#02")
kd = atof(buf); //executing command 3 (setting parameter kd)
else if (cmd == "#03")
ki = atof(buf); //executing command 4 (setting parameter ki)
}
void SendReply()
{
//This is called from the SerialProc function when the #00 command is received
//After the last parameter (TimeDelay) it sends the carrige return characters via the Serial.println
Serial.println("reply");
}