Arduino + VB + Comunicação SerialPort + Dúvidas

Bom dia :wink: Estou a fazer um projeto em VB para ligar Leds de uma casa. Esta casa tem várias divisões.
No programa quando eu quero ligar o led quero enviar para a placa o valor da intensidade desse led e a divisão.
Supondo que queria ligar o led da divisao A na intensidade maxima enviaria o valor: 255A SerialPort1.Write("255A")
Supondo que queria desligar o led da divisao B enviaria o valor: SerialPort1.Write("000B")

Tenho este código para a placa Arduino Uno mas não dá e está a dar erro, alguém pode ajudar :

int PINOH = 13;
int PINOQ=12;
void setup(){
  pinMode(PINOH,OUTPUT);
  pinMode(PINOQ,OUTPUT);
  Serial.begin(9600);
}
void loop (){
  char pwm[4];
  unsigned char pwm_int = 0;
 
  for (int i = 0; i < 3; i++){
    pwm[i] = Serial.read();
}
  pwm[3] = '\0';
  pwm_int = atoi(pwm);
  switch(Serial.read()) {
    case 'H': {
          analogWrite(PINOH, pwm);
          break;
}
    case 'Q': {
          analogWrite(PINOQ, pwm);
          break; }
}
}

Erro:
sketch_mar26a.ino: In function 'void loop()':
sketch_mar26a:21: error: invalid conversion from 'char*' to 'uint8_t'
sketch_mar26a:21: error: initializing argument 2 of 'void digitalWrite(uint8_t, uint8_t)'
sketch_mar26a:25: error: invalid conversion from 'char*' to 'uint8_t'
sketch_mar26a:25: error: initializing argument 2 of 'void digitalWrite(uint8_t, uint8_t)'

Existe um motivo pelo qual o atoi é usado...

int PINOH = 13;
int PINOQ=12;
void setup(){
  pinMode(PINOH,OUTPUT);
  pinMode(PINOQ,OUTPUT);
  Serial.begin(9600);
}
void loop (){
  char pwm[4];
  unsigned char pwm_int = 0;
 
  for (int i = 0; i < 3; i++){
    pwm[i] = Serial.read();
}
  pwm[3] = '\0';
  pwm_int = atoi(pwm);
  switch(Serial.read()) {
    case 'H': {
          analogWrite(PINOH, pwm_int);
          break;
}
    case 'Q': {
          analogWrite(PINOQ, pwm_int);
          break; }
}
}

Tens coisas mal :slight_smile:
Aqui vao elas:

char pwm[4];
unsigned char pwm_int = 0;

Porque estas a declarar estas variaveis na loop ?? Deviam estar logo no inicio.

for (int i = 0; i < 3; i++){
pwm = Serial.read();[/quote]
Como sabes que tens dados para ler e mesmo que os tenhas no buffer nao podes usar um ciclo for, a razao é que a comunicaçao serial é leeeennnttttaaa
e esse for e muito mais rapido.O final disso e que o for ira ser corrido e os dados da serial inda nem chegaram ...
Tens de colocar uma funçao antes para detectares que tens algo no buffer à espera de para ser lido.
Algo assim
if(Serial.available() > 3)doSomething();//Por exemplo ler o buffer
Esta forma apesar de funcionar nao é o correcto, deves colocar um caracter que marca o inicio da comunicao e outro que marque o valor PWM
```

  • switch(Serial.read()) {
       case 'H': {
             analogWrite(PINOH, pwm_int);
             break;
    }
       case 'Q': {
             analogWrite(PINOQ, pwm_int);
             break; }*
    ```
    Forma errada ...
    SerialPort1.Write("255A")
    Estas a escrever 5 bytes na porta.Lembra-te que estas a passar um string e que tambem tem caracter terminador.
    Logo como queres que isso funcione?Como esperas que esse switch avalie o valor?

HugoPT:
Tens coisas mal :slight_smile:
Aqui vao elas:

char pwm[4];
unsigned char pwm_int = 0;

Porque estas a declarar estas variaveis na loop ?? Deviam estar logo no inicio.

Porque motivo é que estas variáveis necessitam de ser globais? (Se houver a detecção de caracteres disponíveis para ler...)
O SerialPort da Microsoft envia um terminador na comunicação série?

int PINOH = 13;
int PINOQ=12;
void setup(){
pinMode(PINOH,OUTPUT);
pinMode(PINOQ,OUTPUT);
Serial.begin(19200);
Serial.println("start");
}
void loop (){
char pwm[4];
unsigned char pwm_int = 0;

if (Serial.available() >= 4) {
//ler PWM
for (int i = 0; i < 3; i++){
pwm = Serial.read();
}

  • pwm[3] = '\0';*
  • pwm_int = atoi(pwm);*
    _ switch(Serial.read()) {_
  • case 'H': {*
  • analogWrite(PINOH, pwm_int);*
    Serial.println(pwm_int);
  • break;*
    }
  • case 'Q': {*
  • analogWrite(PINOQ, pwm_int);*
    Serial.println(pwm_int);
  • break; }*
    }
    }
    }
    [/quote]
    Isto funciona para mim... apesar de haver os problemas que o Hugo indicou.
    Já agora... o pino 13 e 12 do Uno não são pinos de PWM.
    Para experimentares este código, abre o Serial Port... escolhe No Line Ending, escreve 255H ou 005Q e carrega em send. O valor que escreveste é-te reenviado de volta.

HugoPT:
Tens coisas mal :slight_smile:
Aqui vao elas:
...

Eu nunca dei C por isso estou um bocado às cegas...
Como é que fica o código se eu quiser enviar aqueles valores ?

bubulindo:
Isto funciona para mim... apesar de haver os problemas que o Hugo indicou.

Já agora... o pino 13 e 12 do Uno não são pinos de PWM.

Para experimentares este código, abre o Serial Port... escolhe No Line Ending, escreve 255H ou 005Q e carrega em send. O valor que escreveste é-te reenviado de volta.

Não faz nada na mesma bubulindo :s

Estranhamente isso funciona no meu...

Recebes de volta o valor que enviaste? Ou estás à espera que o LED acenda?

bubulindo:
Estranhamente isso funciona no meu...

Recebes de volta o valor que enviaste? Ou estás à espera que o LED acenda?

Envio um valor e mostra-me um caracter estranho ns consola do vb

bubulindo:
Para experimentares este código, abre o Serial Port... escolhe No Line Ending, escreve 255H ou 005Q e carrega em send. O valor que escreveste é-te reenviado de volta.

Eu escrevi isto... estás a fazer isto? Eu referia-me ao Serial Port do Arduino.

Também escrevi isto:

bubulindo:
Já agora... o pino 13 e 12 do Uno não são pinos de PWM.

Que placa estás a usar?

Repara também que eu configurei o código para usar uma baud de 19200... a tua aplicação está configurada para que baud rate?

bubulindo:

bubulindo:
Para experimentares este código, abre o Serial Port... escolhe No Line Ending, escreve 255H ou 005Q e carrega em send. O valor que escreveste é-te reenviado de volta.

Eu escrevi isto... estás a fazer isto? Eu referia-me ao Serial Port do Arduino.

Também escrevi isto:

bubulindo:
Já agora... o pino 13 e 12 do Uno não são pinos de PWM.

Que placa estás a usar?

Repara também que eu configurei o código para usar uma baud de 19200... a tua aplicação está configurada para que baud rate?

Bem visto, tinha que mudar o baud -.-
Agora ja faz o que eu quero no Serial Port do Arduino, nao consigo é no VB, estou a tentar assim :

 Dim i As Integer = TrackBar1.Value
        Dim inta As String
        SerialPort1.Open()
        If i < 10 Then
            inta = "00" & i
        ElseIf i < 100 And i >= 10 Then
            inta = "0" & i
        Else
            inta = i
        End If

        SerialPort1.Write(inta + "H")
        System.Threading.Thread.Sleep(5)
        SerialPort1.Close()

Não será mais simples fazer algo assim:

Dim i As Integer = TrackBar1.Value
SerialPort1.Write(i.toString("D3") + "H")

Nota que sempre que abres e fechas o Serial Port no Windows, o Arduino faz um reset... logo este comando nunca é "ouvido".

O ideal é abrir o Serial Port no início da aplicação e quando fechares a aplicação, fechares o Serial Port. Claro que mais tarde, terás de desactivar o auto-reset para fazer algo disto.

bubulindo:
Não será mais simples fazer algo assim:

Dim i As Integer = TrackBar1.Value

SerialPort1.Write(i.toString("D3") + "H")




Nota que sempre que abres e fechas o Serial Port no Windows, o Arduino faz um reset... logo este comando nunca é "ouvido". 

O ideal é abrir o Serial Port no início da aplicação e quando fechares a aplicação, fechares o Serial Port. Claro que mais tarde, terás de desactivar o auto-reset para fazer algo disto.

Deu assim

Dim i As String = Format(TrackBar1.Value, "000") + "A"
SerialPort1.Write(i)
System.Threading.Thread.Sleep(5)

O pior agora é que eu queria ter 8 divisões distintas e a placa que tenho só tem 6 pinos PWM -.-

ups...

bubulindo:
ups...

Pois, ahah.
E se for utilizar o shield Ethernet ainda fico com menos ou nao?

Depende do shield... Mas é provável...
Qual era o modelo de shield que estavas a pensar usar? Tens a certeza que te queres meter nisso com o que sabes de C?

bubulindo:
Depende do shield... Mas é provável...
Qual era o modelo de shield que estavas a pensar usar? Tens a certeza que te queres meter nisso com o que sabes de C?

O shield é este http://arduino.cc/en/uploads/Main/ArduinoEthernetShield_R3_Front.jpg

Ya vai ser complicado mas era a minha ideia ..

Só queria criar um site simples para desligar e ligar via internet, penso que não é muito complicado (acho eu).
Não sei é até que ponto dá para estar a utilizar o programa em vb e ao mesmo tempo ligar e desligar via ethernet

Sim, com esse shield vais perder pinos com PWM.

bubulindo:
Sim, com esse shield vais perder pinos com PWM.

Ya, o pino 10 pelo menos.
Mas mesmo assim consigo dar a volta, basta tirar uma divisao, sem problema

3... pelas minhas contas.

bubulindo:
3... pelas minhas contas.

Tive a mudar o programa e ficou assim no arduino:

int PinoV = 11;
int PinoH= 10;
int PinoS=9;
int PinoC = 6;
int PinoJ= 5;
int PinoR=7; //Não é PWM
int PinoQ = 4;
int PinoB= 2; //Não é PWM

void setup(){
  pinMode(PinoV,OUTPUT);
  pinMode(PinoH,OUTPUT);
  pinMode(PinoS,OUTPUT);
  pinMode(PinoC,OUTPUT);
  pinMode(PinoJ,OUTPUT);
  pinMode(PinoR,OUTPUT);
  pinMode(PinoQ,OUTPUT);
  pinMode(PinoB,OUTPUT);
  Serial.begin(19200);
}
void loop (){
  char pwm[4];
  unsigned char pwm_int = 0;
 
if (Serial.available() >= 4) {
//ler PWM
  for (int i = 0; i < 3; i++){
    pwm[i] = Serial.read();
}
  pwm[3] = '\0';
  pwm_int = atoi(pwm);
  switch(Serial.read()) {
    case 'V': {
          analogWrite(PinoV, pwm_int);
          Serial.println(pwm_int);
          break;}
    case 'H': {
          analogWrite(PinoH, pwm_int);
          Serial.println(pwm_int);
          break; }
    case 'S': {
          analogWrite(PinoS, pwm_int);
          Serial.println(pwm_int);
          break; }
    case 'C': {
          analogWrite(PinoC, pwm_int);
          Serial.println(pwm_int);
          break; }
    case 'J': {
          analogWrite(PinoJ, pwm_int);
          Serial.println(pwm_int);
          break; }
    case 'R': {
          analogWrite(PinoR, pwm_int);
          Serial.println(pwm_int);
          break; }
    case 'Q': {
          analogWrite(PinoQ, pwm_int);
          Serial.println(pwm_int);
          break; }
    case 'B': {
          analogWrite(PinoB, pwm_int);
          Serial.println(pwm_int);
          break; }
    
    }
}
}

O PinoR e o PinoB não vão ter dimmer, vai ser só ligar e desligar.
Se meter mais uma divisao assim a ligar e desligar só, já dá.