C# királyságok

     Mai bejegyzésben bemutatásra kerül az előre legyártott szekvencia feltöltő program, illetve annak Microblaze-beli értelmezője. A feltöltő program, mint ahogy az a bejegyzés címéből is kiderül, C#-ban készült el. Azt kell mondjam, hogy a C# a tökéletes franciakulcs számomra. Könnyű használni, jól lehet benne felhasználói felületet tervezni, könnyű debugolni, könnyű visszafejteni.

     A program alapját a kedvenc soros portos kommunikációs terminálom illetve annak forráskódja adta, amelyik elerheto itt. Lényege, hogy az inverz kinematika számoló programban kigenerált értékeket fel tudjam tölteni a MicronRam-ba mindenféle fennakadás nélkül. Ezekre az értékekre azért van szükség, mert egyelőre nehéz lenne valós időben kiszámolni a szervók megfelelő pozícióit illetve értékeit.

      A program a következőképpen néz ki :


     Három fontos egysége van: bemeneti, beállítás és kimeneti. A bemeneti részben tudjuk megadni, hogy melyik állományt szeretnénk feltölteni. A beállítások résznél tudjuk kiválasztani a rendelkezésre álló soros portok közül, hogy melyiken keresztül szeretnénk kommunikálni, illetve, hogy melyik "particiót" szeretnénk felülírni. Kimeneti egységek a hiba ablak, az előnézet ablak, illetve az érkezett üzenetek ablak. A hiba ablakba kerül minden, amit a try-catch blokk kidob magából, illetve ide kerülnek a "nem megfelelően formázott " tipusú szövegek is. Az előnézet ablakban láthatjuk a kódot, amit feltöltünk az FPGA-ra. Ugyanitt módosításokat is eszközölhetünk, mivel módosítás esetén az itt megjelenített kód lesz feltöltve, s nem az, ami a szöveges állományban van. Az érkezett üzenetek ablakban jelennek meg az FPGA által küldött üzenetek. Itt kisérhetjük figyelemmel, hogy a küldés sikeres volt, vagy sem.

Fontosabb forráskód részletek :

        private void port_DataReceived(object sender, SerialDataReceivedEventArgs e)
        {
            // If the com port has been closed, do nothing
            if (!port.IsOpen) return;

            // Read all the data waiting in the buffer
            string data = port.ReadExisting();
            AppendTextBox(data + "\r\n");
            //Console.WriteLine(port.ReadExisting());
        }

        public void AppendTextBox(string value)
        {
            if (InvokeRequired)
            {
                this.Invoke(new Action<string>(AppendTextBox), new object[] { value });
                return;
            }
            tbReceived.Text += value;
            tbReceived.SelectionStart = tbReceived.Text.Length;
            tbReceived.ScrollToCaret();
            tbReceived.Refresh();
        }

     A port_DataReceived függvény a soros porton érkező adatokat kezelő szál. Minden egyes alkalommal, mikor valami adat kerül arra a vonalra, meghívódik ez a függvénye (viszont ez nem egy sima függvény, hanem egy szál). Az AppendTextBox függvény segítségével tud a szál a szövegdobozba írni (ilyen izémizé hozzáférési problémák vannak, ha kivülről próbálunk módosítani valamit, amit belülről is lehet... ilyenkor a c# arra ügyel, hogy nehogy egyszerre több helyről módosítsuk... egész királyul meg van oldva...).


        private void Form1_Load(object sender, EventArgs e)
        {
            foreach (string s in SerialPort.GetPortNames()) cbComPort.Items.Add(s);
            for (int i = 1; i < 20;i++ ) cbPartition.Items.Add(i);
            cbComPort.SelectedIndex = 0;
            cbPartition.SelectedIndex = 0;
        }

     Itt mondjuk meg, hogy mit csináljon a program, amikor elindul. Ebben a részben lekérdezzük a rendelkezésre álló soros portokat, valamint feltöltjük a particiokat tartalmazó kombóboxokat a megfelelő értékekkel.


        private void bSend_Click(object sender, EventArgs e)
        {
            //Start the communication
            port.Write(new byte[] {0xFF }, 0, 1);
            // Select the partition
            int part = int.Parse(cbPartition.Text);
            port.Write(new byte[] { Convert.ToByte(part) }, 0, 1);

            for (int ize = 0; ize < 100000000; ize++) ;
            // send the number of lines.
            port.Write(tbLineNum.Text.ToString());
                port.Write(new byte[] { 0x0D }, 0, 1); //Carriage return. 
            input = tbPreview.Text;
            
                string[] fields = input.Split(new char[] { ' ' });

                progressBar1.Maximum = fields.Length;

                for (int i = 0; i < fields.Length; i++)
                {
                    try
                    {
                        int szam = int.Parse(fields[i]);
                        Console.WriteLine("Szam : " + szam);
                        port.Write(new byte[] { Convert.ToByte(szam) }, 0, 1);
                    }
                    catch
                    {
                        Console.WriteLine("Nem szam." + fields[i] + "\n");
                    }
                    progressBar1.Value = i;
                }
                progressBar1.Value = 0;
        }

     Ez történik, amikor megnyomjuk a küldés gombot. A program tudja, milyen lépéseket kell végigjárjon, hogy ne legyen fennakadás a kommunikációban. Ezeket a lépéseket előre le kell szögezni, hogy mindkét fél ismerje. Nagyjából úgy kell elképzelni, mint a TCP protokollt. Startbit, particio választás, csomag hossza, csomag. Csomagvég karakter nincs. Csomag vége utan rögtön következik a másik csomag.

    A programban még lesznek kisebb nagyobb (főként esztétikai jellegű) változtatások, viszont a motor ugyanez marad. Ideálisan alkalmazható az IK-SE programmal, ami az Inverz Kinematika V2.0 részben került bemutatásra.

A programból érkező információt értelmező és feldolgozó MicroBlaze programrészlet a következőképpen néz ki:

//====================================================
// PREMADE SEQUENCE -> INTERRUPT HANDLER FUNCTION
//====================================================
//How to use it?
//
//        I. Send 255 to start the communication.
//        II. Send the number of the Sequence, which you want to erase.
//    III. Send the number of the parts of sequence numbers
//         (if you have 49500 sequence, you send 2.)
//    IV. Send the numbers, which multiplied gives the number of sequences
//          (if you have 49500 sequence, you send (250 and 198) or (220 and 225)
//                      or something similar.)
//    V. Send the sequence values. (expl: 49500 number between 0 and 255)
//    END.
//Set a flag to fill the numbers from 49500 to the 0x0C7000 with 128 <- Not yet implemented
//It would be good, to fill the memory segments with 101888 value =>0xC7000 memory address
//implemented on user program side. TO send 101888 value. Approx. 18 minutes 

void uart_interrupt_handler(void* addr_p)
{ 
//receiving premade sequences from the computer and store them in the MicronRam Memory.
Xuint8 empty;
empty = XUartLite_IsReceiveEmpty(XPAR_RS232_PORT_BASEADDR);
            if (empty == FALSE )
            {
                buchstabe2 = XUartLite_RecvByte(XPAR_RS232_PORT_BASEADDR);
                //xil_printf("Buchstabe : %d pre_seq_stage = %d\n",buchstabe2,pre_seq_stage);
                if((buchstabe2==255)&&(pre_seq_stage==0))    
                {
                pre_seq_stage=10;//START.
                //xil_printf("Start receiving PWM. Send the Sequence number.\n");
                }
                
                if(pre_seq_stage == 1)//Which MemorySEQ?
                {
                    if((buchstabe2<=19)&&(buchstabe2>0))//Limits
                    {
                        //xil_printf("Selected Sequence : %d\n",buchstabe2);
                        premade_sequence = (Xuint8*)XPAR_MICRON_RAM_MEM0_BASEADDR + (2+buchstabe2)*0xC7000;
                        pre_seq_stage = 20;
                        //xil_printf("Send the number of lines.\n");
                    }
                    //else xil_printf("Please select a Sequence memory between 1 and 19 (inclusive).\n");//error message.
                }
                if (pre_seq_stage == 2)//how many numbers in the number of sequences
                {
                    //xil_printf("First Number = %c \n",buchstabe2);
                    num_num = buchstabe2;
                    if (buchstabe2 == 13)
                    {
                        pre_seq_stage =30;
                        c3=c3*18;
                        c3=c3/10;            
                        
                        ////xil_printf("Vegleges szam ertek : %d\n",c3);
                        //xil_printf("Kuldjed a PWM ertekeket.\n");
                    }
                    else if ((buchstabe2>=48)&&(buchstabe2<=57))
                    {
                        c3=c3+(buchstabe2-48);
                        c3=c3*10;
                        //xil_printf("Szam erteke : %d\n",c3);
                    }
                }

                if(pre_seq_stage == 3)//reading the sequence values.
                {
                    premade_sequence[counter] = buchstabe2;
                    //xil_printf("Received value : %d\n",buchstabe2);
                    //xil_printf("Saved value : %d\n",premade_sequence[counter]);
                    //xil_printf("Counter : %d C3 : %d\n",counter,c3);
                    counter = counter+1;
                    if(counter == c3)
                    {
                        c3=0;
                        pre_seq_stage = 0;
                        xil_printf("Vege a dalnak.\n");
                    }
                }
            if (pre_seq_stage==10) pre_seq_stage = 1;
            if (pre_seq_stage==20) pre_seq_stage = 2;
            if (pre_seq_stage==30) pre_seq_stage = 3;
            }
} 

      Röviden ennyi lenne a mai bejegyzés. Remélem este írhatok valami jobbat is, mint pár forráskód.

0 megjegyzés:

Megjegyzés küldése

Return top