Ok, werd bei Gelegenheit den C-Code mal rauskramen.
Druckbare Version
Ok, werd bei Gelegenheit den C-Code mal rauskramen.
Hier sind mal die Quelldateien des Moduls zur Helligkeitsmessung.
Erklären tu ich mal nix... Falls was unklar ist, kannst ja fragen (bevor ich hier ins Blaue rein was erkläre und mir den Wolf tippsle ;-))
Es ist als Anregung gedacht. "Out of the Box" wird es wohl eh nicht laufen...
hell.h
hell.cCode:#ifndef _HELL_H_
#define _HELL_H_
extern void hell_init();
extern void hell_intro();
extern uint8_t hell_loop();
extern void hell_mess_start();
#define HELL_MAX 0x1ff
enum
{
HS_IDLE, // inaktiv
HS_AWAIT_INTRO, // warten auf Schedule von timer1-job
HS_AWAIT_PATTERN_GAP, // warten auf Loch im Anzeigen-MUX
HS_MESS,
HS_MESS_OK,
HS_MESS_TIMEOUT,
HS_MESS_DONE
};
#define HELL_NWERT 16
typedef struct
{
uint8_t debug;
uint8_t state;
uint16_t icr1;
uint16_t max;
uint16_t wert;
uint8_t count;
} hell_t;
extern hell_t hell;
#endif // _HELL_H_
Code:#include <AVR.h>
#include <avr/delay.h>
#include "ports.h"
#include "pattern.h"
#include "timer1-job.h"
#include "hell.h"
#include "main.h"
hell_t hell;
void hell_init()
{
hell.state = HS_IDLE;
// AIN+ als Eingang
MAKE_IN (PORT_AIN0);
CLR (PORT_AIN0);
// disable AC (ACD = 1)
// AC Input Capture on -> disconnect from Input Capture of Timer/Counter1
// AIN0(+) = kein Bandgap
ACSR = (0 << ACD) | (0 << ACIC) | (0 << ACBG);
// AC MUX enable (AC-Input = ADC-MUX-Output, falls ADC disabled)
SFIOR |= (1 << ACME);
ADMUX = 0x7 & PORTC_AIN1;
}
void hell_intro()
{
hell.state = HS_AWAIT_PATTERN_GAP;
hell.max = HELL_MAX;
}
void hell_mess_start()
{
SET_ANODES;
hell.state = HS_MESS;
hell.debug = 0;
// Kathoden wurden in pattern::pattern_out() gesetzt.
// enable AC (ACD = 0)
// AC Input Capture on -> connect to Input Capture of Timer/Counter1
// AIN0(+) = kein Bandgap
ACSR = (0 << ACD) | (1 << ACIC) | (0 << ACBG);
// stop timer1
// disconnect timer1 from output pin OC, no PWM
TCCR1A = 0;
TCCR1B = (1 << ICNC1) | (1 << ICES1);
// Load capacity via AIN- push-pull
cli();
OCR1A = hell.max;
// Reset Timer1
TCNT1 = 0;
// PortC.x Pegel
_delay_loop_1 (30);
// enable Input Capture Interrupt
TIMSK |= (1 << TICIE1) | (1 << OCIE1A);
// start timer 1 at 1/64 (011)
// no clear on compare match
// noise cancel
// input capture edge = raising (mess = AIN(-))
// don't change ICNC1 and ICES1 i.o. not to trigger an IRQ
// clear Timer1 Flags
TIFR = TIFR_T1;
TCCR1B = (1 << ICNC1) | (1 << ICES1) | (1 << CS11) | (1 << CS10);
// here we go!
// start discharging via external resistor
// AIN- to high Z
MAKE_IN (PORTC_AIN1);
CLR (PORTC_AIN1);
sei();
}
uint8_t hell_loop()
{
if (hell.state <= HS_MESS)
return T1_CLAIM;
if (hell.state == HS_MESS_TIMEOUT)
hell.icr1 = hell.max;
hell.state = HS_MESS_DONE;
// disconnect InCapt1 from AC
ACSR = (0 << ACD) | (0 << ACIC);
return T1_DONE;
}
SIGNAL (_handle_icp1_oc1a)
{
hell.icr1 = ICR1;
uint8_t state = HS_MESS_TIMEOUT;
if (ACSR & (1 << ACIC))
state = HS_MESS_OK;
hell.state = state;
SET (PORTC_AIN1);
MAKE_OUT (PORTC_AIN1);
TIMSK &= ~TIMSK_T1;
}
// Bit ACIS in ACSR merkt, ob ein Overflow (OC1A) auftrat,
// denn beim Betreten der ISR wird das OCF1A gelöscht.
void __attribute__((naked))
SIG_OUTPUT_COMPARE1A()
{
cbi (ACSR, ACIC);
rjmp (_handle_icp1_oc1a);
}
void __attribute__((naked))
SIG_INPUT_CAPTURE1()
{
rjmp (_handle_icp1_oc1a);
}
danke
ich werds mal zerpflücken und schaun ob es damit geht.
effectiv kann ich den code garnicht selber nutzen da ich mit bascom auf basic angewiesen bin und daher c-code nicht verwenden kann. aber basic code auf bassis deines c codes zu schreiben sollte auch möglich sein :)
grüße
The Maverick
WO willst du den Code denn einsetzen?
Ich verwende ihn wie gasagt zur Helligkeitssteuerung von LEDs, die auch die Umgebungshelligkeit bestimmen. Da muss der Code schon recht flott sein, sonst flackert die Anzeige, denn die Messungen müssen genau in die Lücken der Soft-PWM eingepasst werden.
Zudem müssen die Messungen bei der Auswertung der Tasterdrucke eingearbeitet werden, damit die Taster keinen Unsinn liefern und die Messung nicht ungültig wird, wenn eigentlich eine Taster-Abfrage ansteht.
Last not least brauche ich zur Messung Timer1. Diesen Timer brauche ich aber noch für andere Teile der Software (Soft-UART, PWM, etc..) und muss daher die Resource "Timer1" über ein Resourcen-Management verwalten. Die Messung wird dann vom Scheduler gestartet. Bei dir kann es also um einiges einfacher werden.
Zu bedenken möchte ich noch geben, daß die Messung recht stark streut und um so länger dauert, je dunkler es ist. Bei Schummerlicht ist die Messung also langsamer als sie mit einem ADC wäre.
Der große Vorteil des Ansatzes ist, daß man praktisch keine extra Hardware braucht. Eine Messung mit dem internen ADC wäre so gar nicht möglich, weil der ADC-Eingang viel zu niederohmig ist.
ich möchte das hier für einsetzen:
https://www.roboternetz.de/phpBB2/ze...hlight=#170976
allerdings ohne taster
ich hab mit dem ADC zu meinem project schon rumgespielt aber das eigenlicht einer led ist scheinbar zu schwach oder ich bekomm den code nicht richtig hin. jedenfalls bekomm ich nennenswerte ausschläge nur wenn ich meine tischleuchte vor die led halte. aber einfach nur den finger auf die blinkende led halten um das rückstrahlende licht zu messen klappt nur minimal :(
für tips wär ich dankbar.
grüße
Tm
Versuchst du etwa, das mit einer Led zu machen? :-k Nö, oder???
bisher hab ichs nur mit einer led getestet :) aber später solls eine 8x8 matrix werden ..
schau dir das project das ich in dem anderen beitrag verlinkt hab an. es geht halt wirklich darum das licht von einer led selbst wieder einzufangen.
also led leuchtet und strahlt ins nichts. wenn mein finger drauf ist geht das licht an meine haut und wird zurückgeworden. das licht soll wieder eingefangen werden und gemessen werden.
https://www.roboternetz.de/phpBB2/vi...c.php?p=207197Zitat:
Zitat von ogni42
Respekt! Ich habe immer schon von der bidirektionalität jedes bauteils geträumt... ;.)