Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Programmieren allgemein (https://www.delphipraxis.net/40-programmieren-allgemein/)
-   -   RGB Farbwerte an einen Mikrocontroller senden (https://www.delphipraxis.net/159677-rgb-farbwerte-einen-mikrocontroller-senden.html)

NiNj4sTy1e 7. Apr 2011 16:44

RGB Farbwerte an einen Mikrocontroller senden
 
Hallo liebe Delphi Gemeinde,

ich hoffe ihr könnt mir bei meinem Problem weiterhelfen und ich hoffe das Thema ist im richtigen Unterforum erstellt ;)

Also mein Vorhaben ist einfach: In Delphi RGB-Farbwerte einstellen/ermitteln per ScrollBar oder Farbkreis, das ist auch kein Problem.
Diese Daten dann als String an einen Mikrocontroller senden, dieser steuert dann eine RGB Leuchtdiode an (werden später mehr).
Der Mikrocontroller ist ein Atmel ATMEGA328P fertig auf eine Platine gelötet als Arduino und hängt am USB.
Für den Arduino habe ich auch schon einen fertigen Code aus dem Internet, dieser funktioniert leider nur mit dem Interface, das der Verfasser in Processing(Java) geschrieben hat.

Ich möchte den Controller allerdings mit Delphi ansprechen. Ein einfaches 'L' um eine LED anzuschalten bzw. ein 'H' um sie auszuschalten konnte ich schon an den Controller senden. Mit TComport das hat der Arduino verstanden, aber wenn ich die dreistelligen RGB Werte sende geht irgendwas schief...

Ich weiß echt nicht mehr weiter, habe leider auch nicht so viel Erfahrung mit sowas. Ca. 30 Stunden Internetsuche haben mein Problem nicht lösen können.

Jetzt folg erstmal eine ganze Menge Code zur Verdeutlichung:

Das ist erstmal der Processing Code, den der Andere benutzt hat, um RGB Farbwerte zu ermitteln und an den Arduino zu schicken:

Das wichtigste im Code ist aber ganz unten hier nochmal extra:
Code:
myPort.write('L');

myPort.write(r);

myPort.write(g);

myPort.write(b);


Code:
import processing.serial.*;

Serial myPort;

PFont font;

int r = 0;

int g = 0;

int b = 0;

void setup() {

size(512, 512);

println(Serial.list());

String portName = Serial.list()[1];

myPort = new Serial(this, portName, 9600);
font = loadFont("AngsanaNew-Bold-48.vlw");

}

void draw() {

background(0, 0, 0);

smooth();

stroke(50, 50, 50);

fill(r, g, b);

rectMode(CORNERS);

rect(20, 20, width / 2 - 10, height - 20);

textFont(font);

textAlign(CENTER, TOP);

text("COLOR!", width - width / 4 - 5, 20);

textAlign(LEFT);

fill(r, 0, 0);

text("R: ", width - width / 2, 292);

textAlign(RIGHT);

text(r, width - 10, 292);

textAlign(LEFT);

fill(0, g, 0);

text("G: ", width - width / 2, 392);

textAlign(RIGHT);

text(g, width - 10, 392);

textAlign(LEFT);

fill(0, 0, b);

text("B: ", width - width / 2, 492);
textAlign(RIGHT);

text(b, width - 10, 492);

g = mouseX / 2;

b = mouseY / 2;

if ((mousePressed == true) && (mouseButton == LEFT) && (r < 251)) {

r += 5;

}

if ((mousePressed == true) && (mouseButton == RIGHT) && (r > 4)) {

r -= 5;

}

myPort.write('L');

myPort.write(r);

myPort.write(g);

myPort.write(b);

}
Das hier ist der Code der auf dem Arduino die Werte empfängt und die Farbe an die RGB LED gibt:

Code:
byte r = 0;

byte g = 0;

byte b = 0;

byte r_pin = 9;

byte g_pin = 10;

byte b_pin = 11;

void setup() {

Serial.begin(9600);

}

void loop() {

if (Serial.available() == 4) {

if (Serial.read() == 'L') {

r = Serial.read();

g = Serial.read();

b = Serial.read();

}

}

analogWrite(r_pin, r);

analogWrite(g_pin, g);

analogWrite(b_pin, b);

}
wichtig hierbei:
Code:
Serial.begin(9600);

}

void loop() {

if (Serial.available() == 4) {

if (Serial.read() == 'L') {

r = Serial.read();

g = Serial.read();

b = Serial.read();

}
So zu guter letzt der Delphi Code mit dem ich eigentlich das machen will, was der Processing Code macht:

Delphi-Quellcode:
unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, CPortCtl, CPort, StdCtrls;

type
  TForm1 = class(TForm)
    ComPort1: TComPort;
    ComDataPacket1: TComDataPacket;
    Button1: TButton;
    Button2: TButton;
    Button4: TButton;
    ScrollBar1: TScrollBar;
    ScrollBar2: TScrollBar;
    ScrollBar3: TScrollBar;
    Label1: TLabel;
    Label2: TLabel;
    Label3: TLabel;
    procedure Button1Click(Sender: TObject);
    procedure Button2Click(Sender: TObject);
    procedure Button4Click(Sender: TObject);
    procedure ScrollBar1Change(Sender: TObject);
    procedure ScrollBar2Change(Sender: TObject);
    procedure ScrollBar3Change(Sender: TObject);

  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  Form1: TForm1;
  r,g,b:integer;

implementation

{$R *.dfm}

procedure TForm1.Button1Click(Sender: TObject);
begin
ComPort1.ShowSetupDialog;
end;


procedure TForm1.Button4Click(Sender: TObject);
begin
begin
  if ComPort1.Connected then
    ComPort1.Close
  else
    ComPort1.Open;
end;
end;

procedure TForm1.ScrollBar1Change(Sender: TObject);
begin
r:=ScrollBar1.Position;
Label1.Caption:=Inttostr(r);
end;

procedure TForm1.ScrollBar2Change(Sender: TObject);
begin
g:=ScrollBar2.Position;
Label2.Caption:=Inttostr(g);
end;

procedure TForm1.ScrollBar3Change(Sender: TObject);
begin
b:=Scrollbar3.Position;
Label3.Caption:=IntToStr(b);
end;
procedure TForm1.Button2Click(Sender: TObject);
begin
ComPort1.WriteStr('L');
ComPort1.WriteStr(Inttostr(r));
ComPort1.WriteStr(Inttostr(g));
ComPort1.WriteStr(Inttostr(b));
end;

end.
Sind einfach 3 ScrollBars an denen ich die Werte für R G B einstelle und dann diese an den Controller sende, was nicht funktioniert :(

Ich hoffe irgendjemand kann mir weiterhelfen. Glaubt bitte nicht ich hätte es nicht selber versucht, aber bin relativ neu in Delphi, in einem anderem Forum, das sich aber eher mit Leuchtdioden beschäftigt meinte jemand es wäre vielleicht besser die Werte als Array zu schicken?
Wie gesagt der Arduino Code geht der Fehler liegt halt daran wie die Daten in Delphi gesendet werden.

Der Gedanke diesen Codebrocken einfach so nachzubauen ohne viel Aufwand, war leider ein Irrtum ;)

Code:
myPort.write('L');

myPort.write(r);

myPort.write(g);

myPort.write(b);
Delphi-Quellcode:
procedure TForm1.Button2Click(Sender: TObject);
begin
ComPort1.WriteStr('L');
ComPort1.WriteStr(Inttostr(r));
ComPort1.WriteStr(Inttostr(g));
ComPort1.WriteStr(Inttostr(b));
end;

SRY für den Roman,

und Danke schonmal.
Hier nochmal der Link ins LED Forum wo ich auch schon nachgefragt hatte:http://www.ledstyles.de/ftopic16488.html

EDIT: Achso ich verwende (leider) Delphi 7 ;)

hathor 7. Apr 2011 17:23

AW: RGB Farbwerte an einen Mikrocontroller senden
 
Ich vermute, dass da etwas Entscheidendes fehlt:

Der ARDUINO ist kein Hellseher.
Woher soll er wissen, was er mit den empfangenen Daten machen soll?

Wenn der ARDUINO 3 Bytes für RGB erwartet, dann musst Du auch 3 Bytes senden:

R:=ScrollBar1.Position;
G:=ScrollBar2.Position;
B:=ScrollBar3.Position;
ComPort1.SENDBYTE(76); // L= 76
ComPort1.SENDBYTE(R);
ComPort1.SENDBYTE(G);
ComPort1.SENDBYTE(B);

Integerwerte kannst Du direkt senden ohne Umwandlung.
Die OnChange-Proceduren kannst Du vereinfachen.

Delphi-Quellcode:
unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls, SynaSer;

type
  TForm1 = class(TForm)
    Button1: TButton;
    Button2: TButton;
    Button4: TButton;
    ScrollBar1: TScrollBar;
    ScrollBar2: TScrollBar;
    ScrollBar3: TScrollBar;
    Label1: TLabel;
    Label2: TLabel;
    Label3: TLabel;
    procedure Button4Click(Sender: TObject);
    procedure ScrollBarChange(Sender: TObject);

  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  Form1: TForm1;
  R,G,B: integer;

implementation

{$R *.dfm}

procedure TForm1.Button4Click(Sender: TObject);
var
    ser:TBlockSerial;
begin
    ser:=TBlockSerial.Create; ser.RaiseExcept:= false;//True;
  try
    ser.Connect('COM1');
    ser.Config(StrToIntDef('9600', 9600),8,'N',2,false,false);
    sleep(20);
    ser.SENDBYTE(76); // L= 76
    ser.SENDBYTE(R);
    ser.SENDBYTE(G);
    ser.SENDBYTE(B);
  finally ser.Free; end;
end;

procedure TForm1.ScrollBarChange(Sender: TObject); //für alle 3 gleich
begin
Label1.Caption:=Inttostr(ScrollBar1.Position);
Label2.Caption:=Inttostr(ScrollBar2.Position);
Label3.Caption:=Inttostr(ScrollBar3.Position);

R:=ScrollBar1.Position;
G:=ScrollBar2.Position;
B:=ScrollBar3.Position;
Button4Click(Self);
end;

NiNj4sTy1e 7. Apr 2011 17:27

AW: RGB Farbwerte an einen Mikrocontroller senden
 
Code:
void loop() {

if (Serial.available() == 4) {

if (Serial.read() == 'L') {

r = Serial.read();

g = Serial.read();

b = Serial.read();

}

}

analogWrite(r_pin, r);

analogWrite(g_pin, g);

analogWrite(b_pin, b);

}
in die Variablen einfügen und dann an die Pins der RGB LED senden.

Aphton 7. Apr 2011 17:27

AW: RGB Farbwerte an einen Mikrocontroller senden
 
Delphi-Quellcode:
{*SNIP*}
ComPort1.WriteStr('L');
ComPort1.WriteStr(Inttostr(r));
ComPort1.WriteStr(Inttostr(g));
ComPort1.WriteStr(Inttostr(b));
{*SNIP*}
Beim Arduino kommt Folgendes an:
"L<r><g><b>" (formatiert)
Also wenn r = 50, g = 100, b = 150, dann würde das so aussehen:
"L50100150"
Weiß dein Arduino damit umzugehen?
Ich würde da lieber noch ein "-" einbauen und im Arduino dann den String wieder in seine Einzelteile zerlegen!

shmia 7. Apr 2011 17:51

AW: RGB Farbwerte an einen Mikrocontroller senden
 
Delphi-Quellcode:
var
  command : AnsiString;
begin
  command := 'L'+Chr(Inttostr(r))+Chr(Inttostr(g))+Chr(Inttostr(b));
  ComPort1.WriteStr(command);
Datenübertragung muss natürlich auf 8-Bit eingestellt sein...

Namenloser 7. Apr 2011 18:15

AW: RGB Farbwerte an einen Mikrocontroller senden
 
Zitat:

Zitat von shmia (Beitrag 1093727)
Delphi-Quellcode:
var
  command : AnsiString;
begin
  command := 'L'+Chr(Inttostr(r))+Chr(Inttostr(g))+Chr(Inttostr(b));
  ComPort1.WriteStr(command);
Datenübertragung muss natürlich auf 8-Bit eingestellt sein...

Wenn schon
Delphi-Quellcode:
var
  command : AnsiString;
begin
  command := 'L'+Chr(r)+Chr(g)+Chr(b);
  ComPort1.WriteStr(command);

NiNj4sTy1e 7. Apr 2011 18:46

AW: RGB Farbwerte an einen Mikrocontroller senden
 
Vielen Dank erstmal, probiere es gleich mal aus, ja der Arduino Code ist nicht so toll, habe den Arduino erst seit Freitag und seit dem ziemlich viel Zeit damit verbracht zu verstehen, aber habe es leider bis jetzt nicht hinbekommen einen String anständig zu zerlegen.
Darum habe ich erstmal einen Code genommen der schon da war. Aber besser wäre natürlich wenn ich z.B. R255G255B255; oder so etwas schicke, aber
da fehlt halt noch das know how

Super das mir so schnell geholfen wird hier, habe so viel in allen möglichen Foren gelesen in den letzten Tagen, auch einiges gelernt, aber
geholfen hat es nicht wirklich.

mfg

hathor 7. Apr 2011 18:52

AW: RGB Farbwerte an einen Mikrocontroller senden
 
Liste der Anhänge anzeigen (Anzahl: 1)
Ich verwende SYNASER für die serielle Schnittstelle:

SYNASER - Serial Port Synchronous Library for Delphi and Kylix

Features of SynaSer

This is list of basic features:

SynaSer is not components, but only classes and routines. Not needed any installation.
Working under Delphi, C++Builder, Kylix or FreePascal.
Supported platforms are Win32 and Linux.
Support for communicating on serial ports in blocking (synchronous) mode.
Supported is high speed of communication. (about few megabytes per second!).
Consume very low CPU time.
Supported is same communication mechanism as used in Synapse TCP/IP library.
Can lock serial port under Linux (like Windows do it).
Support for software and hardware handshake.
You may open any COM port, if exists in you system (i.e. COM156). You can use Windows or Linux
naming of devices on any supported platform!
Support for half-duplex RTS driven communication on all supported systems, include linux, WinNT
or Win9x! (good for RS485 convertors, etc.)
Option for detect device presence before each data transmission.
Support for easy use of AT commands for communicate with modems.

NiNj4sTy1e 7. Apr 2011 19:02

AW: RGB Farbwerte an einen Mikrocontroller senden
 
Muss ich mir mal anschauen ist wahrscheinlich wieder alles anders ;) hatte mich ja gerade erst mit Comport angefreundet.

Klappt super mit:

procedure TForm1.Button2Click(Sender: TObject);
var
command : AnsiString;
begin
command := 'L'+Chr(r)+Chr(g)+Chr(b);
ComPort1.WriteStr(command);
end;

Vielen Dank! Werde mich jetzt mal daran machen den Arduino Code neu zu gestalten :D

mfg


Alle Zeitangaben in WEZ +1. Es ist jetzt 22:58 Uhr.

Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz