====== Charlie Plexing ====== {{wp>Charliplexing}} ist eine möglichkeit durch geschickte Verwendung der drei Zustände $Low$, $High$ und $Z$ (= {{wpde>Tri-state}}) aus durch wenige Pins viele LEDs anzusteuern. Dabei wir ausgenutzt, dass in den hochohmigen Pin, welcher auf $Z$ "liegt", kein Strom fließen kann und dieser auch keinen Spannungswert definiert. ===== Beispiel eines Charlieplexing ===== In ist ein Beispiel für Charlieplexing dargestellt. es ist folgendes zu sehen: * Links ist die gewünschte Outputmatrix zu sehen, in welchem durch Druck auf $H$ bzw. $L$ die gewünschte LED aktiviert bzw. deaktiviert werden kann. * In der Mitte ist die Logik zu sehen, auf die im gleich nochmals eingegangen wird. * Rechts ist die LED Matrix zu finden, welche durch Charlieplexing angesteuert wird. Es soll nun die Logik etwas näher beschrieben werden. Dies kann auch durch Reduktion der Simulationsgeschwindigkeit besser in der Simulation sichtbar gemacht werden: - Es ist ersichtlich, dass jeweils für ein nebeneinander liegendes LED-Pärchen im Charlieplexing Anode und Kathode vertauscht sind. \\ Im Code werden deshalb immer zwei nebeneinander liegende Werte in der Outputmatrix gleichzeitig behandelt. (Siehe Zeile 141ff in ''CharlieP.c'') Dabei ist für die LED links oben ([0][0]) die Kathode gerade der Pin des Ports $PORTx.0$. - UM eine LED leuchten zu lassen wird ein bestimmter Pin eines Ports auf $High$ gesetzt, z.B. $PORTx.0$. Für diesen Pin muss auch das Datenrichtungsregister auf $High$ gesetzt werden, dies geschieht durch das $ODER$-Gatter vor dem $DDRx.0$ Pin. \\ Im Code wird dafür im Zeile 158 und 159 die ''portMatrix'' gefüllt. - Für die LEDs in der ersten Reihe ist $PORTx.0$ entweder die Kathode (jede zweite LED ab [0][0]) oder Anode (jede zweite LED ab [0][1]). \\ Gleiches gilt für die zweite Reihe für $PORTx.1$. Für die dritte Reihe gilt dies nur für die ersten beiden LEDs. \\ Im Code schlägt sich dies in der Ermittlung der ''actCathode'' für ein LED-Pärchen in Zeile 145 bzw. 148 nieder. \\ {{url>https://www.falstad.com/circuit/circuitjs.html?ctz=CQAgzCAMB0l3AmALATjejGAcVYFYw8EA2ARiQSz1KzUgjARDxCQjwFMBaU0gKDBIQAMwDuAEwBOAewAOAHQCOCaC1IgU0Rt15RW0GqkjVI5PAHYURPf1LEm5rEJ7XHz0pCFMxUuUpVqepC4pnyiIOYIwVyREVEgXFg4kGFx0UlpCR5CKeFuWZ4RTgkZuUXOGfkxTGWR0ciZiVCpVQ1VyS3xLg5ddh15xd3lWcT9wzyjjX3NAxWNY3UlOO0LxbGLsbXFeMTDm53BO5n7syXDC-HLXWNOOEe3cTMapExHKC+PZQ+JOO9MP08-iMcN9pmUgUMIWDUqDrKDJuCPgCIScQN9Yt9Si1BtN4asKiCkDgAVshBiiZ8YRTYkDUd8GhCGl8KTxClDCsyQc8mB0ouYQMQjhMcILdlwosEhAAFFJ8gVCjKirLxaX8OVK2JKpCSkBSsB8dUK+Vi7WsXUIA2QfmgwpYOwFITSi1y+lCO1ihrS-U0Q4of7TJXCoIGEAeeDhuChiPwVIanrBVGBq7pJ5J5NLVNC6aLINlezuaz5rJgXayq0Cho8EvMYjRUjVoQAEUbACUAB6wS38vB+4E1uuTaUAeRbABUO2Xu72ATt0jhh2OO2ry0WuEdZwkjk3W0vY5XNZWjikfcxp4qFclcOow9HIzeI3wTz3-iKjcEYNfb-Ao7e926K14ORdgBIANBunogM27bQM65bPmcG5NAu44wY+WC+j0xqfFeP5frhD7hEWioNNkzTqiRhQbqR27QfqcrwbEG6xMhHZ0XBuwIJWDScY6uojihbH8jxoEkfEwk0axwGmlExLcZA858YuqFyhKoHyaGYnqRJynlqQ5i7KQvYvMEhlMNpy5CUIpkJCRvYsQYwE4HpHpWfpZpSvxE7AaQ1jORpJludpx72FMhQ5j5TDeBIMgKMoqihkEIS2LQNlCFmuxHFEqBmseGRVhlYq8K8uwQI6qQArE4pkjU5VgS54A1eE+U1sWJWNa1DWpZ1KQth1jBZG5-XqEw97BAEoHxe+qgwqGcKhm5ZQkdYtntdJWkmdYZRHBFLXCcevm+ZQs0jbWCU1Mwj6+W5LxOddp3DXoeCXZFok4MJdgmaBj3PWpJlHapH1nd94Q7YDoMLakflg9dvaLXep2qTJTzvQj3FMqk22FAg9qkYtONYzjR1lNZN2hkZHzE+TZkmRTqSmkVrAmRykOTKT0zGU87NiVZ8SLTzY1Wcz4RObaGljOQPNcqTXzHWiYvI1Zy38089PWPTtPhNt1iY0BdjuIUXCmgChufRA756MIACGAA2ADOHBPGuJrREKR7la7hXVk7jv1mKWZe2MzVNKycy5e4hW9v1PBGaBLPRMQVn3UTwHNVHvty0IADCAAyKekSbyrEqaWe59nm5IO4XuIenn1W3bDssJO5eV37FdZG3QgANqQAAup3pA9yntbEunXDD+3vHd33vd8GXY-qUHq41wldf28wzRz0SdZe6gnulivNtr43Kdbx1hvoRPZpT53CCD3Khv2kHSCPxLV+953YCD5vL872n1a14fBuG8EjPz9iaKOR4LaAPXk3B+YCQGPwTlfAeH877lnPi7E0F8x6TxQbfWeIDsFCl3pufewRV5AJSHPce3sx6HjISIaBx9740KFDQpBXcUEz3vngNutDeHOA4SAfufcB4ELXHwj2mDEoUJgeI0BoFnBsEijkKB9c5H3wUZWBR9ou631QSfC+2iL66OEfo-Bm8jFKJQBxVR5CmHAPnm9QR3E7GMPUcw9B49Kzj1MTfaeaD+QSMAs3UMuw9GiK-qE+hAsZEONgS-U658Rg6mvvguUHMJjBDyoDThAS86FT4SyV+ET-EpyNBMM4QgADKsChSVkfhBapFl-JZF7Dkuywj35iPvi-NyySeCBS6fkjJvQ245I7sIvBg9DCtOjidEeMcLQg2KGzHEsM0JCDAF7ayYB1kjUgAgFgyzQJDX+lHJBTcECVVfmAA2JSzEjPLNqAcko06nTyQYuULy2lmTTp0-xXzyzXP9KdO54dUkoJ6c8yMgzwlpyGYC6FQkbmR3uQC9+n9UhI1JkjeZzRZl4uskciOByjmxzbAkewEBeAsC4GAKwoYaBmgaKIS2AA7AALhwcQ8hbZDgAK6ctkEKvlABbS2nLJAAEs2x8EpeYSABkSBonuluRRIAADGAALS2khrbSo4Hy2Q1sOBth5Xy+Q8h2XZwAKKNnFZKmVcqQZJI4cSS5dMPWOkWe1bZpLwBe09eEf1VKvAXKAipI2DNkBzjNM04CwkeAfCTRkGpTdpjJoWRmGpLSdpZtlgCdNwE04fCjmmkACaMmFQ+I-CttSS2TALSWYk9aWmEH9GW6wRbK3BR5MU20xTloiGin4OKgRzYwFCHYJgUJrDsi8CO3wsVxrqEnbAWwIUUSzqRNxJdMV-DxTXcGadIVXRohZLEKKy7D0TpPZu+MXUcxXv3WO1diUp0PvGOsQYe6fAHvHQlddp6d08m5LtV9K6j0fo3Y+M9FJ7gUjepB29QH71wcfUcRYyH-1vug8Br9+RljbA4ihwDx6pqhBdEhtE9oFIyj4EAA noborder}} ===== Lib ===== {{microcontrollertechnik:charlieplexing.zip}} Wichtig: * Die vorliegende Lib (und damit der Code unten) ist nur für eine gerade Anzahl von Pins geeignet. * Zudem muss die Anordnung des Charlieplexings wie im folgenden Bild dargestellt eingehalten werden. {{drawio>microcontrollertechnik:CharliePschaltung.svg}} ===== Code ===== ==== CharlieP.h ==== /* * CharlieP.h * * Created: 10.12.2022 22:30:57 * Author: Tim Fischer */ #ifndef CHARLIEP_H_ #define CHARLIEP_H_ //Makros for bit manipulation #define SET_BIT(BYTE, BIT) ((BYTE) |= (1< ==== CharlieP.c ==== /* * CharlieP.c * * Created: 10.12.2022 22:30:48 * Author: Tim Fischer * * The following code drives charlieplexed LED arrays. For this, the array shall have the following structure: * * colNr-> 0 1 2 3 * * rowNr PIN0 ---------------------------- * v | | | | * | | ^ v . . . . . . . . . . . . This is LED[0,3] * 0 ^ v | | * | | ------PIN2 * | | * PIN1 ---------------------------- * | | | | * | | ^ v * 1 ^ v | | * | | ------PIN3 * | | * PIN2 ---------------------------- * | | * | | ------PIN0 * 2 ^ v | | * | | ^ v * | | | | * PIN3 ----------------------------- * * This example is explained more: * - The numbers of pins is PIN_COUNT = 4. * - There are groups of independent LEDs. There are as much groups of independent LEDs as numbers of pins. * - Example for independent LEDs: * - assume only PIN0 is HIGH and all other pins are at high-impedance. * - Then the anode on some LEDs is at 5V. * - For LED[0,1], LED[0,3] and LED[2,3] anode is HIGH. These can independently be activated, by switching their cathode to LOW. * - The active output anode has to be stepped through all PIN_COUNT pins. * - The arrangements of the ANODES can be read from the circuit above: * rowNr, colNr-> 0 1 2 3 * 0 PIN1 PIN0 PIN2 PIN0 * 1 PIN2 PIN1 PIN3 PIN1 * 2 PIN3 PIN2 PIN3 PIN0 * * - The arrangements of the CATHODE is just the groups of columns rearranged (column 1 with 0, column 3 with 2) * The ANODE becomes the CATHODE ans vice versa. * - For PIN_COUNT = 6, the arrangements of the ANODES shall be as follows: * rowNr, colNr-> 0 1 2 3 4 5 * 0 PIN1 PIN0 PIN2 PIN0 PIN3 PIN0 * 1 PIN2 PIN1 PIN3 PIN1 PIN4 PIN1 * 2 PIN3 PIN2 PIN4 PIN2 PIN5 PIN2 * 3 PIN4 PIN3 PIN5 PIN3 PIN4 PIN0 * 4 PIN5 PIN4 PIN5 PIN0 PIN5 PIN1 * * - For PIN_COUNT = 8, the arrangements of the ANODES shall be as follows: * rowNr, colNr-> 0 1 2 3 4 5 6 7 * 0 PIN1 PIN0 PIN2 PIN0 PIN3 PIN0 PIN4 PIN0 * 1 PIN2 PIN1 PIN3 PIN1 PIN4 PIN1 PIN5 PIN1 * 2 PIN3 PIN2 PIN4 PIN2 PIN5 PIN2 PIN6 PIN2 * 3 PIN4 PIN3 PIN5 PIN3 PIN6 PIN3 PIN7 PIN3 * 4 PIN5 PIN4 PIN6 PIN4 PIN7 PIN4 PIN5 PIN9 * 5 PIN6 PIN5 PIN7 PIN5 PIN6 PIN0 PIN6 PIN1 * 6 PIN7 PIN6 PIN7 PIN0 PIN7 PIN1 PIN7 PIN2 * - The systematic is as following: * - every EVEN column (for UPward pointing LED) is a progression of rowNr + colNr + 1 until it reaches PIN_COUNT-1. * After this, the numbers reflect the rowNr+1 * - every ODD column (for DOWNward pointing LED) is a progression of rowNr until rowNr + colNr + 1 reaches PIN_COUNT-1. * After this, it is counting up again from 0 (= actAnode - PIN_COUNT). * */ #include // lib for I/O config #include // lib for Bit variables #include // lib for standard interrupts #include "charlieP.h" // lib for charlie plexing uint8_t outputPort[PIN_COUNT]={ DDR_C, DDR_C, DDR_D, DDR_D, DDR_D, DDR_D, DDR_D, DDR_D, DDR_D, DDR_D, DDR_B, DDR_B}; // This array shows the PORTs used for driving the charlieplexed LEDs uint8_t outputPin [PIN_COUNT]={ PC2, PC3, PD0, PD1, PD2, PD3, PD4, PD5, PD6, PD7, PB0, PB1}; // This array shows the PINs used for driving the charlieplexed LEDs uint8_t outputMatrixXY[PIN_COUNT][PIN_COUNT-1]={}; // this array reflects the LEDs which have to be activated // The dimensions are the same as in the geometry: [column][row] uint8_t portMatrix [PORT_COUNT*2][PIN_COUNT]={ //Definition of Port Nr 0 1 2 3 4 5 6 7 8 9 10 11 // the portMatrix is used to set the wanted ports to output HIGH or low // // When, no output is wanted only the anodes are set to output HIGH // // and the cathodes are set to high impedance (bit in DDRx = 0) /*PORT_B*/ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1< exit with returning 0 actOutputAnode = 0; // when the last anode -> set back to first return DONE; // when the last anode -> exit with returning "DONE" } ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // Mapping des SignalOutput Arrays ========================================================== //mapped die Matrix auf den SignalOutout, um so die LEDs in Gruppen einzuteilen /********************************************************************* * * CharlieP_setPortMatrix * * - maps the outputMatrixXY (xy-matrix of activatable LEDs) to the necessary port and pins * *********************************************************************/ void CharlieP_setPortMatrix() { uint8_t actCathode = 0, actPortCathode = 0, actPinCathode = 0, bitInOutputMatrixForLedUpwards = 0; uint8_t actAnode = 0, actPortAnode = 0, actPinAnode = 0, bitInOutputMatrixForLedDownwards = 0; for (uint8_t rowNr = 0; rowNr = PIN_COUNT) // once the change of the charlie plexing type in the row is reached { // actCathode = actAnode - PIN_COUNT; // recalculate the pin of the actual cathode. For details see comment in the beginning of CharlieP.c actAnode = rowNr + 1; // recalculate the pin of the actual anode. For details see comment in the beginning of CharlieP.c }; actPortCathode = outputPort[actCathode]; // get cathode PIN / PORTs for upward pointing LED, which has to be (de)activated actPinCathode = outputPin [actCathode]; actPortAnode = outputPort[actAnode ]; // get anode PIN / PORTs for upward pointing LED, which has to be (de)activated actPinAnode = outputPin [actAnode ]; CHG_BIT(portMatrix[actPortCathode][actAnode ], actPinCathode, bitInOutputMatrixForLedUpwards ); // change the DDR for the pin and port for the UPward pointing LED CHG_BIT(portMatrix[actPortAnode ][actCathode], actPinAnode, bitInOutputMatrixForLedDownwards); // change the DDR for the pin and port for the DOWNward pointing LED }; }